mirror of
https://github.com/radareorg/radare2.git
synced 2025-02-03 12:12:06 +00:00
Remove flag list in RFlags and just use hashtable (#12703)
* Do not directly use flags->flags, but use r_flags_foreach functions * Remove list of flags because unnecessary * Do not free flagitem when we just need to change the name(aka key) * Use skiplist to iterate, so we get order for free * Use RIOMap instead of RIOSection which is being killed * Free flagitems when ht is freed There's already the hashtable that can serve to iterate all flagitems.
This commit is contained in:
parent
ea92c06e1a
commit
320a258977
@ -3499,10 +3499,22 @@ R_API int r_core_anal_data(RCore *core, ut64 addr, int count, int depth, int wor
|
||||
return true;
|
||||
}
|
||||
|
||||
struct block_flags_stat_t {
|
||||
ut64 step;
|
||||
ut64 from;
|
||||
RCoreAnalStats *as;
|
||||
};
|
||||
|
||||
static bool block_flags_stat(RFlagItem *fi, void *user) {
|
||||
struct block_flags_stat_t *u = (struct block_flags_stat_t *)user;
|
||||
int piece = (fi->offset - u->from) / u->step;
|
||||
u->as->block[piece].flags++;
|
||||
return true;
|
||||
}
|
||||
|
||||
/* core analysis stats */
|
||||
/* stats --- colorful bar */
|
||||
R_API RCoreAnalStats* r_core_anal_get_stats(RCore *core, ut64 from, ut64 to, ut64 step) {
|
||||
RFlagItem *f;
|
||||
RAnalFunction *F;
|
||||
RBinSymbol *S;
|
||||
RListIter *iter;
|
||||
@ -3535,14 +3547,9 @@ R_API RCoreAnalStats* r_core_anal_get_stats(RCore *core, ut64 from, ut64 to, ut6
|
||||
as->block[piece].perm = map ? map->perm: (core->io->desc ? core->io->desc->perm: 0);
|
||||
}
|
||||
// iter all flags
|
||||
r_list_foreach (core->flags->flags, iter, f) {
|
||||
//if (f->offset+f->size < from) continue;
|
||||
if (f->offset < from || f->offset > to) {
|
||||
continue;
|
||||
}
|
||||
piece = (f->offset - from) / step;
|
||||
as->block[piece].flags++;
|
||||
}
|
||||
struct block_flags_stat_t u = { .step = step, .from = from, .as = as };
|
||||
r_flag_foreach_range (core->flags, from, to + 1, block_flags_stat, &u);
|
||||
|
||||
// iter all functions
|
||||
r_list_foreach (core->anal->fcns, iter, F) {
|
||||
if (F->addr < from || F->addr > to) {
|
||||
|
@ -3041,11 +3041,23 @@ static int foreach_comment(void *user, const char *k, const char *v) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
struct exec_command_t {
|
||||
RCore *core;
|
||||
const char *cmd;
|
||||
};
|
||||
|
||||
static bool exec_command_on_flag(RFlagItem *flg, void *u) {
|
||||
struct exec_command_t *user = (struct exec_command_t *)u;
|
||||
r_core_seek (user->core, flg->offset, 1);
|
||||
r_core_block_size (user->core, flg->size);
|
||||
r_core_cmd0 (user->core, user->cmd);
|
||||
return true;
|
||||
}
|
||||
|
||||
R_API int r_core_cmd_foreach3(RCore *core, const char *cmd, char *each) { // "@@@"
|
||||
RDebug *dbg = core->dbg;
|
||||
RList *list, *head;
|
||||
RListIter *iter;
|
||||
RFlagItem *flg;
|
||||
int i;
|
||||
|
||||
switch (each[0]) {
|
||||
@ -3194,13 +3206,9 @@ R_API int r_core_cmd_foreach3(RCore *core, const char *cmd, char *each) { // "@@
|
||||
char *glob = r_str_trim (strdup (each + 1));
|
||||
ut64 off = core->offset;
|
||||
ut64 obs = core->blocksize;
|
||||
r_list_foreach (core->flags->flags, iter, flg) {
|
||||
if (r_str_glob (flg->name, glob)) {
|
||||
r_core_seek (core, flg->offset, 1);
|
||||
r_core_block_size (core, flg->size);
|
||||
r_core_cmd0 (core, cmd);
|
||||
}
|
||||
}
|
||||
|
||||
struct exec_command_t u = { .core = core, .cmd = cmd };
|
||||
r_flag_foreach_glob (core->flags, glob, exec_command_on_flag, &u);
|
||||
r_core_seek (core, off, 0);
|
||||
r_core_block_size (core, obs);
|
||||
free (glob);
|
||||
@ -3278,6 +3286,24 @@ static void foreachOffset (RCore *core, const char *_cmd, const char *each) {
|
||||
free (cmd);
|
||||
}
|
||||
|
||||
struct duplicate_flag_t {
|
||||
RList *ret;
|
||||
const char *word;
|
||||
};
|
||||
|
||||
static bool duplicate_flag(RFlagItem *flag, void *u) {
|
||||
struct duplicate_flag_t *user = (struct duplicate_flag_t *)u;
|
||||
/* filter per flag spaces */
|
||||
if (r_str_glob (flag->name, user->word)) {
|
||||
RFlagItem *cloned_item = r_flag_item_clone (flag);
|
||||
if (!cloned_item) {
|
||||
return false;
|
||||
}
|
||||
r_list_append (user->ret, cloned_item);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
R_API int r_core_cmd_foreach(RCore *core, const char *cmd, char *each) {
|
||||
int i, j;
|
||||
char ch;
|
||||
@ -3585,20 +3611,11 @@ R_API int r_core_cmd_foreach(RCore *core, const char *cmd, char *each) {
|
||||
the command is going to be executed on flags
|
||||
values at the moment the command is called
|
||||
(without side effects) */
|
||||
r_list_foreach (core->flags->flags, iter, flag) {
|
||||
/* filter per flag spaces */
|
||||
if ((flagspace != -1) && (flag->space != flagspace)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (r_str_glob (flag->name, word)) {
|
||||
RFlagItem *cloned_item = r_flag_item_clone (flag);
|
||||
if (!cloned_item) {
|
||||
break;
|
||||
}
|
||||
r_list_append (match_flag_items, cloned_item);
|
||||
}
|
||||
}
|
||||
struct duplicate_flag_t u = {
|
||||
.ret = match_flag_items,
|
||||
.word = word,
|
||||
};
|
||||
r_flag_foreach_space (core->flags, flagspace, duplicate_flag, &u);
|
||||
|
||||
/* for all flags that match */
|
||||
r_list_foreach (match_flag_items, iter, flag) {
|
||||
|
@ -43,7 +43,6 @@ static const char *help_msg_f[] = {
|
||||
"fr"," [old] [[new]]","rename flag (if no new flag current seek one is used)",
|
||||
"fR","[?] [f] [t] [m]","relocate all flags matching f&~m 'f'rom, 't'o, 'm'ask",
|
||||
"fs","[?]+-*","manage flagspaces",
|
||||
"fS","[on]","sort flags by offset or name",
|
||||
"ft","[?]*","flag tags, useful to find all flags matching some words",
|
||||
"fV","[*-] [nkey] [offset]","dump/restore visual marks (mK/'K)",
|
||||
"fx","[d]","show hexdump (or disasm) of flag:flagsize",
|
||||
@ -168,45 +167,56 @@ static void cmd_fz(RCore *core, const char *input) {
|
||||
}
|
||||
}
|
||||
|
||||
struct flagbar_t {
|
||||
RCore *core;
|
||||
int cols;
|
||||
};
|
||||
|
||||
static bool flagbar_foreach(RFlagItem *fi, void *user) {
|
||||
struct flagbar_t *u = (struct flagbar_t *)user;
|
||||
ut64 min = 0, max = r_io_size (u->core->io);
|
||||
RIOMap *m = r_io_map_get (u->core->io, fi->offset);
|
||||
if (m) {
|
||||
min = m->itv.addr;
|
||||
max = m->itv.addr + m->itv.size;
|
||||
}
|
||||
r_cons_printf ("0x%08"PFMT64x" ", fi->offset);
|
||||
r_print_rangebar (u->core->print, fi->offset, fi->offset + fi->size, min, max, u->cols);
|
||||
r_cons_printf (" %s\n", fi->name);
|
||||
return true;
|
||||
}
|
||||
|
||||
static void flagbars(RCore *core, const char *glob) {
|
||||
int cols = r_cons_get_size (NULL);
|
||||
RListIter *iter;
|
||||
RFlagItem *flag;
|
||||
cols -= 80;
|
||||
if (cols < 0) {
|
||||
cols += 80;
|
||||
}
|
||||
r_list_foreach (core->flags->flags, iter, flag) {
|
||||
ut64 min = 0, max = r_io_size (core->io);
|
||||
RIOMap *map = r_io_map_get (core->io, flag->offset);
|
||||
if (map) {
|
||||
min = map->itv.addr;
|
||||
max = map->itv.addr + map->itv.size;
|
||||
}
|
||||
if (r_str_glob (flag->name, glob)) {
|
||||
r_cons_printf ("0x%08"PFMT64x" ", flag->offset);
|
||||
r_print_rangebar (core->print, flag->offset, flag->offset + flag->size, min, max, cols);
|
||||
r_cons_printf (" %s\n", flag->name);
|
||||
}
|
||||
|
||||
struct flagbar_t u = { .core = core, .cols = cols };
|
||||
r_flag_foreach_glob (core->flags, glob, flagbar_foreach, &u);
|
||||
}
|
||||
|
||||
struct flag_to_flag_t {
|
||||
ut64 next;
|
||||
ut64 offset;
|
||||
};
|
||||
|
||||
static bool flag_to_flag_foreach(RFlagItem *fi, void *user) {
|
||||
struct flag_to_flag_t *u = (struct flag_to_flag_t *)user;
|
||||
if (fi->offset < u->next && fi->offset > u->offset) {
|
||||
u->next = fi->offset;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static int flag_to_flag(RCore *core, const char *glob) {
|
||||
RFlagItem *flag;
|
||||
RListIter *iter;
|
||||
ut64 next = UT64_MAX;
|
||||
r_return_val_if_fail (glob, 0);
|
||||
glob = r_str_trim_ro (glob);
|
||||
r_list_foreach (core->flags->flags, iter, flag) {
|
||||
if (flag->offset < next && flag->offset > core->offset) {
|
||||
if (glob && *glob && !r_str_glob (flag->name, glob)) {
|
||||
continue;
|
||||
}
|
||||
next = flag->offset;
|
||||
}
|
||||
}
|
||||
if (next != UT64_MAX && next > core->offset) {
|
||||
return next - core->offset;
|
||||
struct flag_to_flag_t u = { .next = UT64_MAX, .offset = core->offset };
|
||||
r_flag_foreach_glob (core->flags, glob, flag_to_flag_foreach, &u);
|
||||
if (u.next != UT64_MAX && u.next > core->offset) {
|
||||
return u.next - core->offset;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@ -262,23 +272,34 @@ static void cmd_flag_tags (RCore *core, const char *input) {
|
||||
free (inp);
|
||||
}
|
||||
|
||||
struct rename_flag_t {
|
||||
RCore *core;
|
||||
const char *pfx;
|
||||
int count;
|
||||
};
|
||||
|
||||
static bool rename_flag_ordinal(RFlagItem *fi, void *user) {
|
||||
struct rename_flag_t *u = (struct rename_flag_t *)user;
|
||||
char *newName = r_str_newf ("%s%d", u->pfx, u->count++);
|
||||
if (!newName) {
|
||||
return false;
|
||||
}
|
||||
r_flag_rename (u->core->flags, fi, newName);
|
||||
free (newName);
|
||||
return true;
|
||||
}
|
||||
|
||||
static void flag_ordinals(RCore *core, const char *str) {
|
||||
RFlagItem *flag;
|
||||
RListIter *iter;
|
||||
const char *glob = r_str_trim_ro (str);
|
||||
int count = 0;
|
||||
char *pfx = strdup (glob);
|
||||
char *p = strchr (pfx, '*');
|
||||
if (p) {
|
||||
*p = 0;
|
||||
}
|
||||
r_list_foreach (core->flags->flags, iter, flag) {
|
||||
if (r_str_glob (flag->name, glob)) {
|
||||
char *newName = r_str_newf ("%s%d", pfx, count++);
|
||||
r_flag_rename (core->flags, flag, newName);
|
||||
free (newName);
|
||||
}
|
||||
}
|
||||
|
||||
struct rename_flag_t u = { .core = core, .pfx = pfx, .count = 0 };
|
||||
r_flag_foreach_glob (core->flags, glob, rename_flag_ordinal, &u);
|
||||
free (pfx);
|
||||
}
|
||||
|
||||
static int cmpflag(const void *_a, const void *_b) {
|
||||
@ -286,6 +307,39 @@ static int cmpflag(const void *_a, const void *_b) {
|
||||
return (flag1->offset - flag2->offset);
|
||||
}
|
||||
|
||||
struct find_flag_t {
|
||||
RFlagItem *win;
|
||||
ut64 at;
|
||||
};
|
||||
|
||||
static bool find_flag_after(RFlagItem *flag, void *user) {
|
||||
struct find_flag_t *u = (struct find_flag_t *)user;
|
||||
if (flag->offset > u->at && (!u->win || flag->offset < u->win->offset)) {
|
||||
u->win = flag;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool find_flag_after_foreach(RFlagItem *flag, void *user) {
|
||||
if (flag->size != 0) {
|
||||
return true;
|
||||
}
|
||||
|
||||
RFlag *flags = (RFlag *)user;
|
||||
struct find_flag_t u = { .win = NULL, .at = flag->offset };
|
||||
r_flag_foreach (flags, find_flag_after, &u);
|
||||
if (u.win) {
|
||||
flag->size = u.win->offset - flag->offset;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool adjust_offset(RFlagItem *flag, void *user) {
|
||||
st64 base = *(st64 *)user;
|
||||
flag->offset += base;
|
||||
return true;
|
||||
}
|
||||
|
||||
static int cmd_flag(void *data, const char *input) {
|
||||
static int flagenum = 0;
|
||||
RCore *core = (RCore *)data;
|
||||
@ -435,15 +489,10 @@ rep:
|
||||
str = strdup (input + 2);
|
||||
ptr = strchr (str, ' ');
|
||||
if (ptr) {
|
||||
RListIter *iter;
|
||||
RFlagItem *flag;
|
||||
RFlag *f = core->flags;
|
||||
*ptr = 0;
|
||||
base = r_num_math (core->num, str);
|
||||
r_list_foreach (f->flags, iter, flag) {
|
||||
if (r_str_glob (flag->name, ptr+1))
|
||||
flag->offset += base;
|
||||
}
|
||||
r_flag_foreach_glob (f, ptr + 1, adjust_offset, &base);
|
||||
} else {
|
||||
core->flags->base = r_num_math (core->num, input+1);
|
||||
}
|
||||
@ -576,24 +625,7 @@ rep:
|
||||
if (glob) {
|
||||
glob++;
|
||||
}
|
||||
RListIter *iter, *iter2;
|
||||
RFlagItem *flag, *flag2;
|
||||
r_list_foreach (core->flags->flags, iter, flag) {
|
||||
if (flag->size == 0 && (!glob || r_str_glob (flag->name, glob))) {
|
||||
RFlagItem *win = NULL;
|
||||
ut64 at = flag->offset;
|
||||
r_list_foreach (core->flags->flags, iter2, flag2) {
|
||||
if (flag2->offset > at) {
|
||||
if (!win || flag2->offset < win->offset) {
|
||||
win = flag2;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (win) {
|
||||
flag->size = win->offset - flag->offset;
|
||||
}
|
||||
}
|
||||
}
|
||||
r_flag_foreach_glob (core->flags, glob, find_flag_after_foreach, core->flags);
|
||||
} else if (input[1] == ' ') { // "fl ..."
|
||||
char *p, *arg = strdup (input + 2);
|
||||
r_str_trim_head_tail (arg);
|
||||
@ -660,9 +692,6 @@ rep:
|
||||
case 't': // "ft"
|
||||
cmd_flag_tags (core, input);
|
||||
break;
|
||||
case 'S':
|
||||
r_flag_sort (core->flags, (input[1]=='n'));
|
||||
break;
|
||||
case 's': // "fs"
|
||||
switch (input[1]) {
|
||||
case '?':
|
||||
@ -901,16 +930,13 @@ rep:
|
||||
arg++;
|
||||
if (*arg) {
|
||||
RFlag *f = core->flags;
|
||||
RList *temp = r_list_new ();
|
||||
RList *temp = r_flag_all_list (f);
|
||||
ut64 loff = 0;
|
||||
ut64 uoff = 0;
|
||||
ut64 curseek = core->offset;
|
||||
char *lmatch = NULL , *umatch = NULL;
|
||||
RFlagItem *flag;
|
||||
RListIter *iter;
|
||||
r_list_foreach (f->flags, iter, flag) { // creating a local copy
|
||||
r_list_append (temp, flag);
|
||||
}
|
||||
r_list_sort (temp, &cmpflag);
|
||||
r_list_foreach (temp, iter, flag) {
|
||||
if ((f->space_idx != -1) && (flag->space != f->space_idx)) {
|
||||
|
@ -1752,11 +1752,35 @@ R_API void r_core_print_examine(RCore *core, const char *str) {
|
||||
}
|
||||
}
|
||||
|
||||
struct count_pz_t {
|
||||
int flagspace;
|
||||
ut64 addr;
|
||||
ut64 size;
|
||||
int *ret;
|
||||
};
|
||||
|
||||
static bool count_pzs(RFlagItem *fi, void *u) {
|
||||
struct count_pz_t *user = (struct count_pz_t *)u;
|
||||
if (fi->space == user->flagspace &&
|
||||
((user->addr <= fi->offset && fi->offset < user->addr + user->size) ||
|
||||
(user->addr <= fi->offset + fi->size && fi->offset + fi->size < user->addr + user->size))) {
|
||||
(*user->ret)++;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
static bool count_pzf(RFlagItem *fi, void *u) {
|
||||
struct count_pz_t *user = (struct count_pz_t *)u;
|
||||
if (fi->offset <= user->addr && user->addr < fi->offset + fi->size) {
|
||||
(*user->ret)++;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static int printzoomcallback(void *user, int mode, ut64 addr, ut8 *bufz, ut64 size) {
|
||||
RCore *core = (RCore *) user;
|
||||
int j, ret = 0;
|
||||
RListIter *iter;
|
||||
RFlagItem *flag;
|
||||
struct count_pz_t u;
|
||||
|
||||
switch (mode) {
|
||||
case '0': // "pz0"
|
||||
@ -1770,10 +1794,9 @@ static int printzoomcallback(void *user, int mode, ut64 addr, ut8 *bufz, ut64 si
|
||||
ret = (ut8) (r_hash_entropy_fraction (bufz, size) * 255);
|
||||
break;
|
||||
case 'f': // "pzf"
|
||||
r_list_foreach (core->flags->flags, iter, flag)
|
||||
if (flag->offset <= addr && addr < flag->offset + flag->size) {
|
||||
ret++;
|
||||
}
|
||||
u.addr = addr;
|
||||
u.ret = &ret;
|
||||
r_flag_foreach (core->flags, count_pzf, &u);
|
||||
break;
|
||||
case 'F': // "pzF"
|
||||
for (j = 0; j < size; j++) {
|
||||
@ -1791,15 +1814,11 @@ static int printzoomcallback(void *user, int mode, ut64 addr, ut8 *bufz, ut64 si
|
||||
break;
|
||||
case 's': // "pzs"
|
||||
j = r_flag_space_get (core->flags, "strings");
|
||||
r_list_foreach (core->flags->flags, iter, flag) {
|
||||
if (flag->space == j &&
|
||||
((addr <= flag->offset &&
|
||||
flag->offset < addr + size) ||
|
||||
(addr <= flag->offset + flag->size &&
|
||||
flag->offset + flag->size < addr + size))) {
|
||||
ret++;
|
||||
}
|
||||
}
|
||||
u.flagspace = j;
|
||||
u.addr = addr;
|
||||
u.size = size;
|
||||
u.ret = &ret;
|
||||
r_flag_foreach (core->flags, count_pzs, &u);
|
||||
break;
|
||||
case 'h': // "pzh" head
|
||||
default:
|
||||
|
@ -1140,23 +1140,20 @@ static void autocomplete_breakpoints(RLine* line, const char* str) {
|
||||
line->completion.argv = tmp_argv;
|
||||
}
|
||||
|
||||
static bool add_argv(RFlagItem *fi, void *user) {
|
||||
int *i = (int *)user;
|
||||
tmp_argv[(*i)++] = fi->name;
|
||||
return *i != TMP_ARGV_SZ - 1;
|
||||
}
|
||||
|
||||
static void autocomplete_flags(RLine* line, const char* str) {
|
||||
RCore *core = line->user;
|
||||
if (!core || !str) {
|
||||
return;
|
||||
}
|
||||
RListIter *iter;
|
||||
RFlagItem *flag;
|
||||
int n, i = 0;
|
||||
n = strlen (str);
|
||||
r_list_foreach (core->flags->flags, iter, flag) {
|
||||
if (!strncmp (flag->name, str, n)) {
|
||||
tmp_argv[i++] = flag->name;
|
||||
if (i == (TMP_ARGV_SZ - 1)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
r_flag_foreach_prefix (core->flags, str, n, add_argv, &i);
|
||||
tmp_argv[i] = NULL;
|
||||
line->completion.argc = i;
|
||||
line->completion.argv = tmp_argv;
|
||||
@ -1461,7 +1458,6 @@ static bool find_autocomplete(RLine *line) {
|
||||
static int autocomplete(RLine *line) {
|
||||
RCore *core = line->user;
|
||||
RListIter *iter;
|
||||
RFlagItem *flag;
|
||||
if (core) {
|
||||
r_core_free_autocomplete (core);
|
||||
char *pipe = strchr (line->buffer.data, '>');
|
||||
@ -1473,14 +1469,7 @@ static int autocomplete(RLine *line) {
|
||||
ptr = (char *)r_str_trim_ro (ptr + 1);
|
||||
n = strlen (ptr);//(line->buffer.data+sdelta);
|
||||
sdelta = (int)(size_t)(ptr - line->buffer.data);
|
||||
r_list_foreach (core->flags->flags, iter, flag) {
|
||||
if (!strncmp (flag->name, line->buffer.data+sdelta, n)) {
|
||||
tmp_argv[i++] = flag->name;
|
||||
if (i == TMP_ARGV_SZ - 1) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
r_flag_foreach_prefix (core->flags, line->buffer.data + sdelta, n, add_argv, &i);
|
||||
tmp_argv[i] = NULL;
|
||||
line->completion.argc = i;
|
||||
line->completion.argv = tmp_argv;
|
||||
|
@ -14,6 +14,12 @@ enum {
|
||||
R_QWORD_DATA = 8
|
||||
};
|
||||
|
||||
enum {
|
||||
SORT_NONE,
|
||||
SORT_NAME,
|
||||
SORT_OFFSET
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
RCore *core;
|
||||
int t_idx;
|
||||
@ -858,9 +864,16 @@ R_API bool r_core_visual_hudclasses(RCore *core) {
|
||||
return res? true: false;
|
||||
}
|
||||
|
||||
static bool hudstuff_append(RFlagItem *fi, void *user) {
|
||||
RList *list = (RList *)user;
|
||||
char *s = r_str_newf ("0x%08"PFMT64x" %s", fi->offset, fi->name);
|
||||
if (s) {
|
||||
r_list_append (list, s);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
R_API bool r_core_visual_hudstuff(RCore *core) {
|
||||
RListIter *iter;
|
||||
RFlagItem *flag;
|
||||
ut64 addr;
|
||||
char *res;
|
||||
RList *list = r_list_new ();
|
||||
@ -868,10 +881,7 @@ R_API bool r_core_visual_hudstuff(RCore *core) {
|
||||
return false;
|
||||
}
|
||||
list->free = free;
|
||||
r_list_foreach (core->flags->flags, iter, flag) {
|
||||
r_list_append (list, r_str_newf ("0x%08"PFMT64x" %s",
|
||||
flag->offset, flag->name));
|
||||
}
|
||||
r_flag_foreach (core->flags, hudstuff_append, list);
|
||||
sdb_foreach (core->anal->sdb_meta, cmtcb, list);
|
||||
res = r_cons_hud (list, NULL);
|
||||
if (res) {
|
||||
@ -1201,8 +1211,40 @@ R_API int r_core_visual_classes(RCore *core) {
|
||||
return true;
|
||||
}
|
||||
|
||||
static int flag_name_sort(const void *a, const void *b) {
|
||||
const RFlagItem *fa = (const RFlagItem *)a;
|
||||
const RFlagItem *fb = (const RFlagItem *)b;
|
||||
return strcmp (fa->name, fb->name);
|
||||
}
|
||||
|
||||
static int flag_offset_sort(const void *a, const void *b) {
|
||||
const RFlagItem *fa = (const RFlagItem *)a;
|
||||
const RFlagItem *fb = (const RFlagItem *)b;
|
||||
if (fa->offset < fb->offset) {
|
||||
return -1;
|
||||
}
|
||||
if (fa->offset > fb->offset) {
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void sort_flags(RList *l, int sort) {
|
||||
switch (sort) {
|
||||
case SORT_NAME:
|
||||
r_list_sort (l, flag_name_sort);
|
||||
break;
|
||||
case SORT_OFFSET:
|
||||
r_list_sort (l, flag_offset_sort);
|
||||
break;
|
||||
case SORT_NONE:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
typedef void (*PrintItemCallback)(void *user, void *p, bool selected);
|
||||
static void *widget_list (void *user, RList *list, int rows, int cur, PrintItemCallback cb) {
|
||||
static void *widget_list(void *user, RList *list, int rows, int cur, PrintItemCallback cb) {
|
||||
void *item, *curItem = NULL;
|
||||
RListIter *iter;
|
||||
int count = 0;
|
||||
@ -1544,14 +1586,13 @@ R_API int r_core_visual_view_rop(RCore *core) {
|
||||
R_API int r_core_visual_trackflags(RCore *core) {
|
||||
const char *fs = NULL, *fs2 = NULL;
|
||||
int hit, i, j, ch;
|
||||
RListIter *iter;
|
||||
RFlagItem *flag;
|
||||
int _option = 0;
|
||||
int option = 0;
|
||||
char cmd[1024];
|
||||
int format = 0;
|
||||
int delta = 7;
|
||||
int menu = 0;
|
||||
int sort = SORT_NONE;
|
||||
|
||||
for (j=i=0; i<R_FLAG_SPACES_MAX; i++) {
|
||||
if (core->flags->spaces[i]) {
|
||||
@ -1570,14 +1611,18 @@ R_API int r_core_visual_trackflags(RCore *core) {
|
||||
(core->flags->space_idx==-1)?"*":core->flags->spaces[core->flags->space_idx]);
|
||||
hit = 0;
|
||||
i = j = 0;
|
||||
r_list_foreach (core->flags->flags, iter, flag) {
|
||||
RList *l = r_flag_all_list (core->flags);
|
||||
RListIter *iter;
|
||||
RFlagItem *fi;
|
||||
sort_flags (l, sort);
|
||||
r_list_foreach (l, iter, fi) {
|
||||
/* filter per flag spaces */
|
||||
if ((core->flags->space_idx != -1) &&
|
||||
(flag->space != core->flags->space_idx)) {
|
||||
(fi->space != core->flags->space_idx)) {
|
||||
continue;
|
||||
}
|
||||
if (option == i) {
|
||||
fs2 = flag->name;
|
||||
fs2 = fi->name;
|
||||
hit = 1;
|
||||
}
|
||||
if ((i>=option-delta) && ((i<option+delta)||((option<delta)&&(i<(delta<<1))))) {
|
||||
@ -1586,7 +1631,7 @@ R_API int r_core_visual_trackflags(RCore *core) {
|
||||
r_cons_printf (Color_INVERT);
|
||||
}
|
||||
r_cons_printf (" %c %03d 0x%08"PFMT64x" %4"PFMT64d" %s\n",
|
||||
cur?'>':' ', i, flag->offset, flag->size, flag->name);
|
||||
cur?'>':' ', i, fi->offset, fi->size, fi->name);
|
||||
if (cur && hasColor) {
|
||||
r_cons_printf (Color_RESET);
|
||||
}
|
||||
@ -1594,6 +1639,8 @@ R_API int r_core_visual_trackflags(RCore *core) {
|
||||
}
|
||||
i++;
|
||||
}
|
||||
r_list_free (l);
|
||||
|
||||
if (!hit && i > 0) {
|
||||
option = i - 1;
|
||||
continue;
|
||||
@ -1667,8 +1714,8 @@ R_API int r_core_visual_trackflags(RCore *core) {
|
||||
}
|
||||
break;
|
||||
case 'J': option += 10; break;
|
||||
case 'o': r_flag_sort (core->flags, 0); break;
|
||||
case 'n': r_flag_sort (core->flags, 1); break;
|
||||
case 'o': sort = SORT_OFFSET; break;
|
||||
case 'n': sort = SORT_NAME; break;
|
||||
case 'j': option++; break;
|
||||
case 'k':
|
||||
if (--option < 0) {
|
||||
@ -3087,6 +3134,26 @@ beach:
|
||||
r_config_set_i (core->config, "asm.bytes", asmbytes);
|
||||
}
|
||||
|
||||
struct seek_flag_offset_t {
|
||||
ut64 offset;
|
||||
ut64 *next;
|
||||
bool is_next;
|
||||
};
|
||||
|
||||
static bool seek_flag_offset(RFlagItem *fi, void *user) {
|
||||
struct seek_flag_offset_t *u = (struct seek_flag_offset_t *)user;
|
||||
if (u->is_next) {
|
||||
if (fi->offset < *u->next && fi->offset > u->offset) {
|
||||
*u->next = fi->offset;
|
||||
}
|
||||
} else {
|
||||
if (fi->offset > *u->next && fi->offset < u->offset) {
|
||||
*u->next = fi->offset;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
R_API void r_core_seek_next(RCore *core, const char *type) {
|
||||
RListIter *iter;
|
||||
ut64 next = UT64_MAX;
|
||||
@ -3106,21 +3173,11 @@ R_API void r_core_seek_next(RCore *core, const char *type) {
|
||||
}
|
||||
} else if (strstr (type, "hit")) {
|
||||
const char *pfx = r_config_get (core->config, "search.prefix");
|
||||
RFlagItem *flag;
|
||||
r_list_foreach (core->flags->flags, iter, flag) {
|
||||
if (!strncmp (flag->name, pfx, strlen (pfx))) {
|
||||
if (flag->offset < next && flag->offset > core->offset) {
|
||||
next = flag->offset;
|
||||
}
|
||||
}
|
||||
}
|
||||
struct seek_flag_offset_t u = { .offset = core->offset, .next = &next, .is_next = true };
|
||||
r_flag_foreach_prefix (core->flags, pfx, -1, seek_flag_offset, &u);
|
||||
} else { // flags
|
||||
RFlagItem *flag;
|
||||
r_list_foreach (core->flags->flags, iter, flag) {
|
||||
if (flag->offset < next && flag->offset > core->offset) {
|
||||
next = flag->offset;
|
||||
}
|
||||
}
|
||||
struct seek_flag_offset_t u = { .offset = core->offset, .next = &next, .is_next = true };
|
||||
r_flag_foreach (core->flags, seek_flag_offset, &u);
|
||||
}
|
||||
if (next != UT64_MAX) {
|
||||
r_core_seek (core, next, 1);
|
||||
@ -3142,22 +3199,12 @@ R_API void r_core_seek_previous (RCore *core, const char *type) {
|
||||
}
|
||||
} else
|
||||
if (strstr (type, "hit")) {
|
||||
RFlagItem *flag;
|
||||
const char *pfx = r_config_get (core->config, "search.prefix");
|
||||
r_list_foreach (core->flags->flags, iter, flag) {
|
||||
if (!strncmp (flag->name, pfx, strlen (pfx))) {
|
||||
if (flag->offset > next && flag->offset < core->offset) {
|
||||
next = flag->offset;
|
||||
}
|
||||
}
|
||||
}
|
||||
struct seek_flag_offset_t u = { .offset = core->offset, .next = &next, .is_next = false };
|
||||
r_flag_foreach_prefix (core->flags, pfx, -1, seek_flag_offset, &u);
|
||||
} else { // flags
|
||||
RFlagItem *flag;
|
||||
r_list_foreach (core->flags->flags, iter, flag) {
|
||||
if (flag->offset > next && flag->offset < core->offset) {
|
||||
next = flag->offset;
|
||||
}
|
||||
}
|
||||
struct seek_flag_offset_t u = { .offset = core->offset, .next = &next, .is_next = false };
|
||||
r_flag_foreach (core->flags, seek_flag_offset, &u);
|
||||
}
|
||||
if (next != 0) {
|
||||
r_core_seek (core, next, 1);
|
||||
|
@ -2,6 +2,6 @@ include ../config.mk
|
||||
|
||||
NAME=r_flag
|
||||
DEPS=r_util
|
||||
OBJS=flag.o sort.o spaces.o zones.o tags.o
|
||||
OBJS=flag.o spaces.o zones.o tags.o
|
||||
|
||||
include ../rules.mk
|
||||
|
387
libr/flag/flag.c
387
libr/flag/flag.c
@ -7,8 +7,8 @@
|
||||
|
||||
R_LIB_VERSION(r_flag);
|
||||
|
||||
#define ISNULLSTR(x) (!(x) || !*(x))
|
||||
#define IS_IN_SPACE(f, i) ((f)->space_idx != -1 && (i)->space != (f)->space_idx)
|
||||
#define IS_FI_NOTIN_SPACE(f, i) ((f)->space_idx != -1 && (i)->space != (f)->space_idx)
|
||||
#define IS_FI_IN_SPACE(fi, spidx) ((spidx) == -1 || (fi)->space == (spidx))
|
||||
|
||||
static const char *str_callback(RNum *user, ut64 off, int *ok) {
|
||||
RFlag *f = (RFlag*)user;
|
||||
@ -101,7 +101,12 @@ static bool set_name(RFlagItem *item, const char *name) {
|
||||
return true;
|
||||
}
|
||||
|
||||
R_API RFlag * r_flag_new() {
|
||||
static void ht_free_flag(HtPPKv *kv) {
|
||||
free (kv->key);
|
||||
r_flag_item_free (kv->value);
|
||||
}
|
||||
|
||||
R_API RFlag *r_flag_new() {
|
||||
int i;
|
||||
RFlag *f = R_NEW0 (RFlag);
|
||||
if (!f) {
|
||||
@ -120,19 +125,13 @@ R_API RFlag * r_flag_new() {
|
||||
f->zones = NULL;
|
||||
#endif
|
||||
f->tags = sdb_new0 ();
|
||||
f->flags = r_list_new ();
|
||||
if (!f->flags) {
|
||||
r_flag_free (f);
|
||||
return NULL;
|
||||
}
|
||||
f->flags->free = (RListFree) r_flag_item_free;
|
||||
f->space_idx = -1;
|
||||
f->spacestack = r_list_newf (NULL);
|
||||
if (!f->spacestack) {
|
||||
r_flag_free (f);
|
||||
return NULL;
|
||||
}
|
||||
f->ht_name = ht_pp_new0 ();
|
||||
f->ht_name = ht_pp_new (NULL, ht_free_flag, NULL);
|
||||
f->by_off = r_skiplist_new (flag_skiplist_free, flag_skiplist_cmp);
|
||||
#if R_FLAG_ZONE_USE_SDB
|
||||
sdb_free (f->zones);
|
||||
@ -187,7 +186,6 @@ R_API RFlag *r_flag_free(RFlag *f) {
|
||||
r_skiplist_free (f->by_off);
|
||||
ht_pp_free (f->ht_name);
|
||||
|
||||
r_list_free (f->flags);
|
||||
sdb_free (f->tags);
|
||||
r_list_free (f->spacestack);
|
||||
r_num_free (f->num);
|
||||
@ -195,14 +193,93 @@ R_API RFlag *r_flag_free(RFlag *f) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static bool print_flag_name(RFlagItem *fi, void *user) {
|
||||
RFlag *flag = (RFlag *)user;
|
||||
flag->cb_printf ("%s\n", fi->name);
|
||||
return true;
|
||||
}
|
||||
|
||||
struct print_flag_t {
|
||||
RFlag *f;
|
||||
bool in_range;
|
||||
ut64 range_from;
|
||||
ut64 range_to;
|
||||
int fs;
|
||||
bool first;
|
||||
bool real;
|
||||
const char *pfx;
|
||||
};
|
||||
|
||||
static bool print_flag_json(RFlagItem *flag, void *user) {
|
||||
struct print_flag_t *u = (struct print_flag_t *)user;
|
||||
if (u->in_range && (flag->offset < u->range_from || flag->offset >= u->range_to)) {
|
||||
return true;
|
||||
}
|
||||
u->f->cb_printf ("%s{\"name\":\"%s\",\"size\":%" PFMT64d ",",
|
||||
u->first? "": ",", flag->name, flag->size);
|
||||
if (flag->alias) {
|
||||
u->f->cb_printf ("\"alias\":\"%s\"", flag->alias);
|
||||
} else {
|
||||
u->f->cb_printf ("\"offset\":%"PFMT64d, flag->offset);
|
||||
}
|
||||
if (flag->comment) {
|
||||
u->f->cb_printf (",\"comment\":\"}");
|
||||
} else {
|
||||
u->f->cb_printf ("}");
|
||||
}
|
||||
u->first = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool print_flag_rad(RFlagItem *flag, void *user) {
|
||||
struct print_flag_t *u = (struct print_flag_t *)user;
|
||||
if (u->in_range && (flag->offset < u->range_from || flag->offset >= u->range_to)) {
|
||||
return true;
|
||||
}
|
||||
if (u->fs == -1 || flag->space != u->fs) {
|
||||
u->fs = flag->space;
|
||||
const char *flagspace = r_flag_space_get_i (u->f, u->fs);
|
||||
if (!flagspace || !*flagspace) {
|
||||
flagspace = "*";
|
||||
}
|
||||
u->f->cb_printf ("fs %s\n", flagspace);
|
||||
}
|
||||
if (flag->alias) {
|
||||
u->f->cb_printf ("fa %s %s\n", flag->name, flag->alias);
|
||||
if (flag->comment && *flag->comment) {
|
||||
u->f->cb_printf ("\"fC %s %s\"\n",
|
||||
flag->name, flag->comment);
|
||||
}
|
||||
} else {
|
||||
u->f->cb_printf ("f %s %"PFMT64d" 0x%08"PFMT64x"%s%s %s\n",
|
||||
flag->name, flag->size, flag->offset,
|
||||
u->pfx? "+": "", u->pfx? u->pfx: "",
|
||||
flag->comment? flag->comment:"");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool print_flag_orig_name(RFlagItem *flag, void *user) {
|
||||
struct print_flag_t *u = (struct print_flag_t *)user;
|
||||
if (u->in_range && (flag->offset < u->range_from || flag->offset >= u->range_to)) {
|
||||
return true;
|
||||
}
|
||||
if (flag->alias) {
|
||||
const char *n = u->real? flag->realname: flag->name;
|
||||
u->f->cb_printf ("%s %"PFMT64d" %s\n", flag->alias, flag->size, n);
|
||||
} else {
|
||||
const char *n = u->real? flag->realname: (u->f->realnames? flag->realname: flag->name);
|
||||
u->f->cb_printf ("0x%08"PFMT64x" %"PFMT64d" %s\n", flag->offset, flag->size, n);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/* print with r_cons the flag items in the flag f, given as a parameter */
|
||||
R_API void r_flag_list(RFlag *f, int rad, const char *pfx) {
|
||||
bool in_range = false;
|
||||
ut64 range_from = UT64_MAX;
|
||||
ut64 range_to = UT64_MAX;
|
||||
int fs = -1;
|
||||
RListIter *iter;
|
||||
RFlagItem *flag;
|
||||
if (rad == 'i') {
|
||||
char *sp, *arg = strdup (pfx + 1);
|
||||
sp = strchr (arg, ' ');
|
||||
@ -227,106 +304,47 @@ R_API void r_flag_list(RFlag *f, int rad, const char *pfx) {
|
||||
|
||||
switch (rad) {
|
||||
case 'q':
|
||||
r_list_foreach (f->flags, iter, flag) {
|
||||
if (IS_IN_SPACE (f, flag)) {
|
||||
continue;
|
||||
}
|
||||
f->cb_printf ("%s\n", flag->name);
|
||||
}
|
||||
r_flag_foreach_space (f, f->space_idx, print_flag_name, f);
|
||||
break;
|
||||
case 'j': {
|
||||
int first = 1;
|
||||
f->cb_printf ("[");
|
||||
r_list_foreach (f->flags, iter, flag) {
|
||||
if (IS_IN_SPACE (f, flag)) {
|
||||
continue;
|
||||
}
|
||||
if (in_range && (flag->offset < range_from || flag->offset >= range_to)) {
|
||||
continue;
|
||||
}
|
||||
f->cb_printf ("%s{\"name\":\"%s\",\"size\":%"PFMT64d",",
|
||||
first?"":",", flag->name, flag->size);
|
||||
if (flag->alias) {
|
||||
f->cb_printf ("\"alias\":\"%s\"", flag->alias);
|
||||
} else {
|
||||
f->cb_printf ("\"offset\":%"PFMT64d, flag->offset);
|
||||
}
|
||||
if (flag->comment) {
|
||||
f->cb_printf (",\"comment\":\"}");
|
||||
} else {
|
||||
f->cb_printf ("}");
|
||||
}
|
||||
first = 0;
|
||||
}
|
||||
struct print_flag_t u = {
|
||||
.f = f,
|
||||
.in_range = in_range,
|
||||
.range_from = range_from,
|
||||
.range_to = range_to,
|
||||
.first = true
|
||||
};
|
||||
r_flag_foreach_space (f, f->space_idx, print_flag_json, &u);
|
||||
f->cb_printf ("]\n");
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 1:
|
||||
case '*':
|
||||
r_list_foreach (f->flags, iter, flag) {
|
||||
if (IS_IN_SPACE (f, flag)) {
|
||||
continue;
|
||||
}
|
||||
if (in_range && (flag->offset < range_from || flag->offset >= range_to)) {
|
||||
continue;
|
||||
}
|
||||
if (fs == -1 || flag->space != fs) {
|
||||
fs = flag->space;
|
||||
const char *flagspace = r_flag_space_get_i (f, fs);
|
||||
if (!flagspace || !*flagspace) {
|
||||
flagspace = "*";
|
||||
}
|
||||
f->cb_printf ("fs %s\n", flagspace);
|
||||
}
|
||||
if (flag->alias) {
|
||||
f->cb_printf ("fa %s %s\n", flag->name, flag->alias);
|
||||
if (flag->comment && *flag->comment) {
|
||||
f->cb_printf ("\"fC %s %s\"\n",
|
||||
flag->name, flag->comment);
|
||||
}
|
||||
} else {
|
||||
f->cb_printf ("f %s %"PFMT64d" 0x%08"PFMT64x"%s%s %s\n",
|
||||
flag->name, flag->size, flag->offset,
|
||||
pfx?"+":"", pfx?pfx:"",
|
||||
flag->comment? flag->comment:"");
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 'n': // show original name
|
||||
r_list_foreach (f->flags, iter, flag) {
|
||||
if (IS_IN_SPACE (f, flag)) {
|
||||
continue;
|
||||
}
|
||||
if (in_range && (flag->offset < range_from || flag->offset >= range_to)) {
|
||||
continue;
|
||||
}
|
||||
if (flag->alias) {
|
||||
f->cb_printf ("%s %"PFMT64d" %s\n",
|
||||
flag->alias, flag->size, flag->realname);
|
||||
} else {
|
||||
f->cb_printf ("0x%08"PFMT64x" %"PFMT64d" %s\n",
|
||||
flag->offset, flag->size, flag->realname);
|
||||
}
|
||||
}
|
||||
case '*': {
|
||||
struct print_flag_t u = {
|
||||
.f = f,
|
||||
.in_range = in_range,
|
||||
.range_from = range_from,
|
||||
.range_to = range_to,
|
||||
.fs = fs,
|
||||
.pfx = pfx
|
||||
};
|
||||
r_flag_foreach_space (f, f->space_idx, print_flag_rad, &u);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
r_list_foreach (f->flags, iter, flag) {
|
||||
if (IS_IN_SPACE (f, flag)) {
|
||||
continue;
|
||||
}
|
||||
if (in_range && (flag->offset < range_from || flag->offset >= range_to)) {
|
||||
continue;
|
||||
}
|
||||
if (flag->alias) {
|
||||
f->cb_printf ("%s %"PFMT64d" %s\n",
|
||||
flag->alias, flag->size, flag->name);
|
||||
} else {
|
||||
f->cb_printf ("0x%08"PFMT64x" %"PFMT64d" %s\n",
|
||||
flag->offset, flag->size, f->realnames ? flag->realname : flag->name);
|
||||
}
|
||||
}
|
||||
case 'n': { // show original name
|
||||
struct print_flag_t u = {
|
||||
.f = f,
|
||||
.in_range = in_range,
|
||||
.range_from = range_from,
|
||||
.range_to = range_to,
|
||||
.real = (rad == 'n')
|
||||
};
|
||||
r_flag_foreach_space (f, f->space_idx, print_flag_orig_name, &u);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static RFlagItem *evalFlag(RFlag *f, RFlagItem *item) {
|
||||
@ -453,7 +471,7 @@ R_API RFlagItem *r_flag_get_at(RFlag *f, ut64 off, bool closest) {
|
||||
}
|
||||
while (!nice && flags_at) {
|
||||
r_list_foreach (flags_at->flags, iter, item) {
|
||||
if (f->space_strict && IS_IN_SPACE (f, item)) {
|
||||
if (f->space_strict && IS_FI_NOTIN_SPACE (f, item)) {
|
||||
continue;
|
||||
}
|
||||
if (item->offset == off) {
|
||||
@ -472,6 +490,20 @@ R_API RFlagItem *r_flag_get_at(RFlag *f, ut64 off, bool closest) {
|
||||
return nice? evalFlag (f, nice): NULL;
|
||||
}
|
||||
|
||||
static bool append_to_list(void *user, const void *k, const void *v) {
|
||||
RList *ret = (RList *)user;
|
||||
r_list_append (ret, (RFlagItem *)v);
|
||||
return true;
|
||||
}
|
||||
|
||||
R_API RList *r_flag_all_list(RFlag *f) {
|
||||
RList *ret = r_list_new ();
|
||||
if (ret) {
|
||||
ht_pp_foreach (f->ht_name, append_to_list, ret);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* return the list of flag items that are associated with a given offset */
|
||||
R_API const RList* /*<RFlagItem*>*/ r_flag_get_list(RFlag *f, ut64 off) {
|
||||
const RFlagsAtOffset *item = r_flag_get_nearest_list (f, off, 0);
|
||||
@ -535,10 +567,7 @@ R_API RFlagItem *r_flag_set(RFlag *f, const char *name, ut64 off, ut32 size) {
|
||||
r_flag_item_free (item);
|
||||
return NULL;
|
||||
}
|
||||
//item share ownership prone to uaf, that is why only
|
||||
//f->flags has set up free pointer
|
||||
ht_pp_insert (f->ht_name, item->name, item);
|
||||
r_list_append (f->flags, item);
|
||||
}
|
||||
|
||||
item->space = f->space_idx;
|
||||
@ -571,14 +600,14 @@ R_API RFlagItem *r_flag_set(RFlag *f, const char *name, ut64 off, ut32 size) {
|
||||
R_API void r_flag_item_set_alias(RFlagItem *item, const char *alias) {
|
||||
r_return_if_fail (item);
|
||||
free (item->alias);
|
||||
item->alias = ISNULLSTR (alias)? NULL: strdup (alias);
|
||||
item->alias = R_STR_ISEMPTY (alias)? NULL: strdup (alias);
|
||||
}
|
||||
|
||||
/* add/replace/remove the comment of a flag item */
|
||||
R_API void r_flag_item_set_comment(RFlagItem *item, const char *comment) {
|
||||
r_return_if_fail (item);
|
||||
free (item->comment);
|
||||
item->comment = ISNULLSTR (comment) ? NULL : strdup (comment);
|
||||
item->comment = R_STR_ISEMPTY (comment) ? NULL : strdup (comment);
|
||||
}
|
||||
|
||||
/* add/replace/remove the realname of a flag item */
|
||||
@ -587,7 +616,7 @@ R_API void r_flag_item_set_realname(RFlagItem *item, const char *realname) {
|
||||
if (item->name != item->realname) {
|
||||
free (item->realname);
|
||||
}
|
||||
item->realname = ISNULLSTR (realname) ? NULL : strdup (realname);
|
||||
item->realname = R_STR_ISEMPTY (realname)? NULL: strdup (realname);
|
||||
}
|
||||
|
||||
/* change the name of a flag item, if the new name is available.
|
||||
@ -595,7 +624,11 @@ R_API void r_flag_item_set_realname(RFlagItem *item, const char *realname) {
|
||||
R_API int r_flag_rename(RFlag *f, RFlagItem *item, const char *name) {
|
||||
r_return_val_if_fail (f && item && name && *name, false);
|
||||
|
||||
// TODO: add API in ht to update the key of an existing element
|
||||
HtPPKvFreeFunc ofreefn = f->ht_name->opt.freefn;
|
||||
f->ht_name->opt.freefn = NULL;
|
||||
ht_pp_delete (f->ht_name, item->name);
|
||||
f->ht_name->opt.freefn = ofreefn;
|
||||
if (!set_name (item, name)) {
|
||||
return false;
|
||||
}
|
||||
@ -611,7 +644,6 @@ R_API bool r_flag_unset(RFlag *f, RFlagItem *item) {
|
||||
r_return_val_if_fail (f && item, false);
|
||||
remove_offsetmap (f, item);
|
||||
ht_pp_delete (f->ht_name, item->name);
|
||||
r_list_delete_data (f->flags, item);
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -626,26 +658,30 @@ R_API bool r_flag_unset_off(RFlag *f, ut64 off) {
|
||||
return false;
|
||||
}
|
||||
|
||||
struct unset_foreach_t {
|
||||
RFlag *f;
|
||||
int n;
|
||||
};
|
||||
|
||||
static bool unset_foreach(RFlagItem *fi, void *user) {
|
||||
struct unset_foreach_t *u = (struct unset_foreach_t *)user;
|
||||
if (IS_FI_NOTIN_SPACE (u->f, fi)) {
|
||||
return true;
|
||||
}
|
||||
r_flag_unset (u->f, fi);
|
||||
u->n++;
|
||||
return true;
|
||||
}
|
||||
|
||||
/* unset all the flag items that satisfy the given glob.
|
||||
* return the number of unset items. -1 on error */
|
||||
// XXX This is O(n^n) because unset_globa iterates all flags and unset too.
|
||||
R_API int r_flag_unset_glob(RFlag *f, const char *glob) {
|
||||
r_return_val_if_fail (f, -1);
|
||||
|
||||
RListIter *iter, *iter2;
|
||||
RFlagItem *flag;
|
||||
int n = 0;
|
||||
|
||||
r_list_foreach_safe (f->flags, iter, iter2, flag) {
|
||||
if (IS_IN_SPACE (f, flag)) {
|
||||
continue;
|
||||
}
|
||||
if (r_str_glob (flag->name, glob)) {
|
||||
r_flag_unset (f, flag);
|
||||
n++;
|
||||
}
|
||||
}
|
||||
return n;
|
||||
struct unset_foreach_t u = { .f = f, .n = 0 };
|
||||
r_flag_foreach_glob (f, glob, unset_foreach, &u);
|
||||
return u.n;
|
||||
}
|
||||
|
||||
/* unset the flag item with the given name.
|
||||
@ -660,33 +696,45 @@ R_API bool r_flag_unset_name(RFlag *f, const char *name) {
|
||||
R_API void r_flag_unset_all(RFlag *f) {
|
||||
r_return_if_fail (f);
|
||||
f->space_idx = -1;
|
||||
r_list_free (f->flags);
|
||||
f->flags = r_list_newf ((RListFree)r_flag_item_free);
|
||||
ht_pp_free (f->ht_name);
|
||||
//don't set free since f->flags will free up items when needed avoiding uaf
|
||||
f->ht_name = ht_pp_new0 ();
|
||||
f->ht_name = ht_pp_new (NULL, ht_free_flag, NULL);
|
||||
r_skiplist_purge (f->by_off);
|
||||
r_flag_space_unset (f, NULL);
|
||||
}
|
||||
|
||||
struct flag_relocate_t {
|
||||
ut64 off;
|
||||
ut64 off_mask;
|
||||
ut64 neg_mask;
|
||||
ut64 to;
|
||||
int n;
|
||||
};
|
||||
|
||||
static bool flag_relocate_foreach(RFlagItem *fi, void *user) {
|
||||
struct flag_relocate_t *u = (struct flag_relocate_t *)user;
|
||||
ut64 fn = fi->offset & u->neg_mask;
|
||||
ut64 on = u->off & u->neg_mask;
|
||||
if (fn == on) {
|
||||
ut64 fm = fi->offset & u->off_mask;
|
||||
ut64 om = u->to & u->off_mask;
|
||||
fi->offset = (u->to & u->neg_mask) + fm + om;
|
||||
u->n++;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
R_API int r_flag_relocate(RFlag *f, ut64 off, ut64 off_mask, ut64 to) {
|
||||
r_return_val_if_fail (f, -1);
|
||||
ut64 neg_mask = ~(off_mask);
|
||||
RFlagItem *item;
|
||||
RListIter *iter;
|
||||
int n = 0;
|
||||
struct flag_relocate_t u = {
|
||||
.off = off,
|
||||
.off_mask = off_mask,
|
||||
.neg_mask = ~(off_mask),
|
||||
.to = to,
|
||||
.n = 0
|
||||
};
|
||||
|
||||
r_list_foreach (f->flags, iter, item) {
|
||||
ut64 fn = item->offset & neg_mask;
|
||||
ut64 on = off & neg_mask;
|
||||
if (fn == on) {
|
||||
ut64 fm = item->offset & off_mask;
|
||||
ut64 om = to & off_mask;
|
||||
item->offset = (to&neg_mask) + fm + om;
|
||||
n++;
|
||||
}
|
||||
}
|
||||
return n;
|
||||
r_flag_foreach (f, flag_relocate_foreach, &u);
|
||||
return u.n;
|
||||
}
|
||||
|
||||
R_API bool r_flag_move(RFlag *f, ut64 at, ut64 to) {
|
||||
@ -725,15 +773,52 @@ R_API void r_flag_bind(RFlag *f, RFlagBind *fb) {
|
||||
fb->pop_fs = r_flag_space_pop;
|
||||
}
|
||||
|
||||
static bool flag_count_foreach(RFlagItem *fi, void *user) {
|
||||
int *count = (int *)user;
|
||||
(*count)++;
|
||||
return true;
|
||||
}
|
||||
|
||||
R_API int r_flag_count(RFlag *f, const char *glob) {
|
||||
int count = 0;
|
||||
RFlagItem *flag;
|
||||
RListIter *iter;
|
||||
r_return_val_if_fail (f, -1);
|
||||
r_list_foreach (f->flags, iter, flag) {
|
||||
if (r_str_glob (flag->name, glob)) {
|
||||
count++;
|
||||
}
|
||||
}
|
||||
|
||||
r_flag_foreach_glob (f, glob, flag_count_foreach, &count);
|
||||
return count;
|
||||
}
|
||||
|
||||
#define FOREACH_BODY(condition) \
|
||||
RSkipListNode *it, *tmp; \
|
||||
RFlagsAtOffset *flags_at; \
|
||||
RListIter *it2, *tmp2; \
|
||||
RFlagItem *fi; \
|
||||
r_skiplist_foreach_safe (f->by_off, it, tmp, flags_at) { \
|
||||
r_list_foreach_safe (flags_at->flags, it2, tmp2, fi) { \
|
||||
if (condition) { \
|
||||
if (!cb (fi, user)) { \
|
||||
return; \
|
||||
} \
|
||||
} \
|
||||
} \
|
||||
}
|
||||
|
||||
R_API void r_flag_foreach(RFlag *f, RFlagItemCb cb, void *user) {
|
||||
FOREACH_BODY (true);
|
||||
}
|
||||
|
||||
R_API void r_flag_foreach_prefix(RFlag *f, const char *pfx, int pfx_len, RFlagItemCb cb, void *user) {
|
||||
pfx_len = pfx_len < 0? strlen (pfx): pfx_len;
|
||||
FOREACH_BODY (!strncmp (fi->name, pfx, pfx_len));
|
||||
}
|
||||
|
||||
R_API void r_flag_foreach_range(RFlag *f, ut64 from, ut64 to, RFlagItemCb cb, void *user) {
|
||||
FOREACH_BODY (fi->offset >= from && fi->offset < to);
|
||||
}
|
||||
|
||||
R_API void r_flag_foreach_glob(RFlag *f, const char *glob, RFlagItemCb cb, void *user) {
|
||||
FOREACH_BODY (!glob || r_str_glob (fi->name, glob));
|
||||
}
|
||||
|
||||
R_API void r_flag_foreach_space(RFlag *f, int space, RFlagItemCb cb, void *user) {
|
||||
FOREACH_BODY (IS_FI_IN_SPACE (fi, space));
|
||||
}
|
||||
|
@ -1,6 +1,5 @@
|
||||
r_flag_sources = [
|
||||
'flag.c',
|
||||
'sort.c',
|
||||
'tags.c',
|
||||
'spaces.c',
|
||||
'zones.c'
|
||||
|
@ -1,58 +0,0 @@
|
||||
/* radare - LGPL - Copyright 2007-2018 pancake */
|
||||
|
||||
#include <r_flag.h>
|
||||
|
||||
/* compare names */
|
||||
static int ncmp(const void *a, const void *b) {
|
||||
RFlagItem *fa = (RFlagItem *)a;
|
||||
RFlagItem *fb = (RFlagItem *)b;
|
||||
return strcmp (fa->name, fb->name);
|
||||
}
|
||||
|
||||
/* compare offsets */
|
||||
static int cmp(const void *a, const void *b) {
|
||||
RFlagItem *fa = (RFlagItem *)a;
|
||||
RFlagItem *fb = (RFlagItem *)b;
|
||||
if (fa->offset > fb->offset) {
|
||||
return 1;
|
||||
}
|
||||
if (fa->offset < fb->offset) {
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
R_API bool r_flag_sort(RFlag *f, int namesort) {
|
||||
r_return_val_if_fail (f, false);
|
||||
bool ret = false;
|
||||
bool changes = false;
|
||||
RFlagItem *flag, *fi = NULL;
|
||||
RListIter *iter, *it_elem;
|
||||
RList *tmp = r_list_new ();
|
||||
// find bigger ones after this
|
||||
if (!tmp) {
|
||||
return false;
|
||||
}
|
||||
do {
|
||||
changes = false;
|
||||
fi = NULL;
|
||||
r_list_foreach (f->flags, iter, flag) {
|
||||
if (!fi || ((namesort)? ncmp (fi, flag): cmp (fi, flag)) > 0) {
|
||||
fi = flag;
|
||||
it_elem = iter;
|
||||
changes = true;
|
||||
}
|
||||
}
|
||||
if (fi && changes) {
|
||||
ret = true;
|
||||
r_list_split_iter (f->flags, it_elem);
|
||||
free (it_elem);
|
||||
r_list_append (tmp, fi);
|
||||
}
|
||||
} while (changes);
|
||||
|
||||
free (f->flags);
|
||||
f->flags = tmp;
|
||||
f->flags->free = free;
|
||||
return ret;
|
||||
}
|
@ -90,9 +90,12 @@ R_API int r_flag_space_set(RFlag *f, const char *name) {
|
||||
return f->space_idx;
|
||||
}
|
||||
|
||||
static bool unset_space(RFlagItem *fi, void *user) {
|
||||
fi->space = -1;
|
||||
return true;
|
||||
}
|
||||
|
||||
R_API int r_flag_space_unset(RFlag *f, const char *fs) {
|
||||
RListIter *iter;
|
||||
RFlagItem *fi;
|
||||
r_return_val_if_fail (f, false);
|
||||
int i, count = 0;
|
||||
for (i = 0; i < R_FLAG_SPACES_MAX; i++) {
|
||||
@ -105,27 +108,23 @@ R_API int r_flag_space_unset(RFlag *f, const char *fs) {
|
||||
}
|
||||
R_FREE (f->spaces[i]);
|
||||
// remove all flags space references
|
||||
r_list_foreach (f->flags, iter, fi) {
|
||||
if (fi->space == i) {
|
||||
fi->space = -1;
|
||||
}
|
||||
}
|
||||
r_flag_foreach_space (f, i, unset_space, NULL);
|
||||
count++;
|
||||
}
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
static bool space_count(RFlagItem *fi, void *user) {
|
||||
int *count = (int *)user;
|
||||
(*count)++;
|
||||
return true;
|
||||
}
|
||||
|
||||
static int r_flag_space_count(RFlag *f, int n) {
|
||||
RListIter *iter;
|
||||
int count = 0;
|
||||
RFlagItem *fi;
|
||||
if (n != -1) {
|
||||
r_list_foreach (f->flags, iter, fi) {
|
||||
if (fi->space == n) {
|
||||
count++;
|
||||
}
|
||||
}
|
||||
r_flag_foreach_space (f, n, space_count, &count);
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
@ -32,22 +32,32 @@ R_API void r_flag_tags_reset(RFlag *f, const char *name) {
|
||||
sdb_reset (f->tags);
|
||||
}
|
||||
|
||||
struct iter_glob_flag_t {
|
||||
RList *res;
|
||||
RList *words;
|
||||
};
|
||||
|
||||
static bool iter_glob_flag(RFlagItem *fi, void *user) {
|
||||
struct iter_glob_flag_t *u = (struct iter_glob_flag_t *)user;
|
||||
RListIter *iter;
|
||||
const char *word;
|
||||
|
||||
r_list_foreach (u->words, iter, word) {
|
||||
if (r_str_glob (fi->name, word)) {
|
||||
r_list_append (u->res, fi);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
R_API RList *r_flag_tags_get(RFlag *f, const char *name) {
|
||||
r_return_val_if_fail (f && name, NULL);
|
||||
const char *k = sdb_fmt ("tag.%s", name);
|
||||
RListIter *iter, *iter2;
|
||||
const char *word;
|
||||
RFlagItem *flag;
|
||||
char *words = sdb_get (f->tags, k, NULL);
|
||||
RList *res = r_list_newf (NULL);
|
||||
RList *list = r_str_split_list (words, " ");
|
||||
r_list_foreach (f->flags, iter2, flag) {
|
||||
r_list_foreach (list, iter, word) {
|
||||
if (r_str_glob (flag->name, word)) {
|
||||
r_list_append (res, flag);
|
||||
}
|
||||
}
|
||||
}
|
||||
struct iter_glob_flag_t u = { .res = res, .words = list };
|
||||
r_flag_foreach (f, iter_glob_flag, &u);
|
||||
r_list_free (list);
|
||||
return res;
|
||||
}
|
||||
|
@ -58,7 +58,6 @@ typedef struct r_flag_t {
|
||||
RNum *num;
|
||||
RSkipList *by_off; /* flags sorted by offset, value=RFlagsAtOffset */
|
||||
HtPP *ht_name; /* hashmap key=item name, value=RList of items */
|
||||
RList *flags; /* list of RFlagItem contained in the flag */
|
||||
RList *spacestack;
|
||||
PrintfCallback cb_printf;
|
||||
#if R_FLAG_ZONE_USE_SDB
|
||||
@ -81,6 +80,8 @@ typedef int (*RFlagSetSpace)(RFlag *f, const char *name);
|
||||
typedef bool (*RFlagPopSpace)(RFlag *f);
|
||||
typedef bool (*RFlagPushSpace)(RFlag *f, const char *name);
|
||||
|
||||
typedef bool (*RFlagItemCb)(RFlagItem *fi, void *user);
|
||||
|
||||
typedef struct r_flag_bind_t {
|
||||
int init;
|
||||
RFlag *f;
|
||||
@ -108,6 +109,7 @@ R_API RFlagItem *r_flag_get(RFlag *f, const char *name);
|
||||
R_API RFlagItem *r_flag_get_i(RFlag *f, ut64 off);
|
||||
R_API RFlagItem *r_flag_get_i2(RFlag *f, ut64 off);
|
||||
R_API RFlagItem *r_flag_get_at(RFlag *f, ut64 off, bool closest);
|
||||
R_API RList *r_flag_all_list(RFlag *f);
|
||||
R_API const RList* /*<RFlagItem*>*/ r_flag_get_list(RFlag *f, ut64 off);
|
||||
R_API char *r_flag_get_liststr(RFlag *f, ut64 off);
|
||||
R_API bool r_flag_unset(RFlag *f, RFlagItem *item);
|
||||
@ -116,7 +118,6 @@ R_API bool r_flag_unset_off(RFlag *f, ut64 addr);
|
||||
R_API void r_flag_unset_all (RFlag *f);
|
||||
R_API RFlagItem *r_flag_set(RFlag *fo, const char *name, ut64 addr, ut32 size);
|
||||
R_API RFlagItem *r_flag_set_next(RFlag *fo, const char *name, ut64 addr, ut32 size);
|
||||
R_API bool r_flag_sort(RFlag *f, int namesort);
|
||||
R_API void r_flag_item_set_alias(RFlagItem *item, const char *alias);
|
||||
R_API void r_flag_item_free (RFlagItem *item);
|
||||
R_API void r_flag_item_set_comment(RFlagItem *item, const char *comment);
|
||||
@ -127,6 +128,11 @@ R_API int r_flag_rename(RFlag *f, RFlagItem *item, const char *name);
|
||||
R_API int r_flag_relocate(RFlag *f, ut64 off, ut64 off_mask, ut64 to);
|
||||
R_API bool r_flag_move (RFlag *f, ut64 at, ut64 to);
|
||||
R_API const char *r_flag_color(RFlag *f, RFlagItem *it, const char *color);
|
||||
R_API void r_flag_foreach(RFlag *f, RFlagItemCb cb, void *user);
|
||||
R_API void r_flag_foreach_prefix(RFlag *f, const char *pfx, int pfx_len, RFlagItemCb cb, void *user);
|
||||
R_API void r_flag_foreach_range(RFlag *f, ut64 from, ut64 to, RFlagItemCb cb, void *user);
|
||||
R_API void r_flag_foreach_glob(RFlag *f, const char *glob, RFlagItemCb cb, void *user);
|
||||
R_API void r_flag_foreach_space(RFlag *f, int space, RFlagItemCb cb, void *user);
|
||||
|
||||
/* spaces */
|
||||
R_API int r_flag_space_get(RFlag *f, const char *name);
|
||||
|
Loading…
x
Reference in New Issue
Block a user