2020-01-18 17:40:24 +01:00
|
|
|
|
/* radare - LGPL - Copyright 2009-2020 - pancake */
|
2016-05-02 22:52:41 -04:00
|
|
|
|
|
2016-07-03 21:57:00 +02:00
|
|
|
|
#include <stddef.h>
|
2016-05-02 22:52:41 -04:00
|
|
|
|
#include "r_cons.h"
|
|
|
|
|
#include "r_core.h"
|
2012-02-27 02:40:27 +01:00
|
|
|
|
|
2017-07-26 06:14:06 -07:00
|
|
|
|
static const char *help_msg_f[] = {
|
|
|
|
|
"Usage: f","[?] [flagname]", " # Manage offset-name flags",
|
|
|
|
|
"f","","list flags (will only list flags from selected flagspaces)",
|
|
|
|
|
"f?","flagname","check if flag exists or not, See ?? and ?!",
|
|
|
|
|
"f."," [*[*]]","list local per-function flags (*) as r2 commands",
|
|
|
|
|
"f.","blah=$$+12","set local function label named 'blah'",
|
2019-09-02 00:37:20 +02:00
|
|
|
|
"f."," fname","list all local labels for the given function",
|
2020-01-18 17:40:24 +01:00
|
|
|
|
"f,","","table output for flags",
|
2017-07-26 06:14:06 -07:00
|
|
|
|
"f*","","list flags in r commands",
|
|
|
|
|
"f"," name 12 @ 33","set flag 'name' with length 12 at offset 33",
|
|
|
|
|
"f"," name = 33","alias for 'f name @ 33' or 'f name 1 33'",
|
|
|
|
|
"f"," name 12 33 [cmt]","same as above + optional comment",
|
|
|
|
|
"f-",".blah@fcn.foo","delete local label from function at current seek (also f.-)",
|
|
|
|
|
"f--","","delete all flags and flagspaces (deinit)",
|
|
|
|
|
"f+","name 12 @ 33","like above but creates new one if doesnt exist",
|
|
|
|
|
"f-","name","remove flag 'name'",
|
|
|
|
|
"f-","@addr","remove flag at address expression",
|
|
|
|
|
"f="," [glob]","list range bars graphics with flag offsets and sizes",
|
|
|
|
|
"fa"," [name] [alias]","alias a flag to evaluate an expression",
|
|
|
|
|
"fb"," [addr]","set base address for new flags",
|
|
|
|
|
"fb"," [addr] [flag*]","move flags matching 'flag' to relative addr",
|
|
|
|
|
"fc","[?][name] [color]","set color for given flag",
|
|
|
|
|
"fC"," [name] [cmt]","set comment for given flag",
|
2020-02-26 21:24:12 +08:00
|
|
|
|
"fd","[?] addr","return flag+delta",
|
2017-07-26 06:14:06 -07:00
|
|
|
|
"fe-","","resets the enumerator counter",
|
|
|
|
|
"fe"," [name]","create flag name.#num# enumerated flag. See fe?",
|
2017-11-23 14:34:07 +01:00
|
|
|
|
"ff"," ([glob])","distance in bytes to reach the next flag (see sn/sp)",
|
2017-07-26 06:14:06 -07:00
|
|
|
|
"fi"," [size] | [from] [to]","show flags in current block or range",
|
2019-05-18 11:47:00 +02:00
|
|
|
|
"fg","[*] ([prefix])","construct a graph with the flag names",
|
2017-07-26 06:14:06 -07:00
|
|
|
|
"fj","","list flags in JSON format",
|
|
|
|
|
"fl"," (@[flag]) [size]","show or set flag length (size)",
|
|
|
|
|
"fla"," [glob]","automatically compute the size of all flags matching glob",
|
|
|
|
|
"fm"," addr","move flag at current offset to new address",
|
|
|
|
|
"fn","","list flags displaying the real name (demangled)",
|
2019-01-28 10:11:11 +01:00
|
|
|
|
"fnj","","list flags displaying the real name (demangled) in JSON format",
|
2019-04-19 22:45:36 +02:00
|
|
|
|
"fN","","show real name of flag at current address",
|
|
|
|
|
"fN"," [[name]] [realname]","set flag real name (if no flag name current seek one is used)",
|
2017-07-26 06:14:06 -07:00
|
|
|
|
"fo","","show fortunes",
|
2017-12-02 02:11:22 +01:00
|
|
|
|
"fO", " [glob]", "flag as ordinals (sym.* func.* method.*)",
|
2017-07-26 06:14:06 -07:00
|
|
|
|
//" fc [name] [cmt] ; set execution command for a specific flag"
|
2019-04-19 22:45:36 +02:00
|
|
|
|
"fr"," [[old]] [new]","rename flag (if no new flag current seek one is used)",
|
2017-07-26 06:14:06 -07:00
|
|
|
|
"fR","[?] [f] [t] [m]","relocate all flags matching f&~m 'f'rom, 't'o, 'm'ask",
|
|
|
|
|
"fs","[?]+-*","manage flagspaces",
|
2018-05-11 17:18:36 +02:00
|
|
|
|
"ft","[?]*","flag tags, useful to find all flags matching some words",
|
2017-07-26 06:14:06 -07:00
|
|
|
|
"fV","[*-] [nkey] [offset]","dump/restore visual marks (mK/'K)",
|
|
|
|
|
"fx","[d]","show hexdump (or disasm) of flag:flagsize",
|
2017-10-23 12:54:03 +02:00
|
|
|
|
"fq","","list flags in quiet mode",
|
2017-07-26 06:14:06 -07:00
|
|
|
|
"fz","[?][name]","add named flag zone -name to delete. see fz?[name]",
|
|
|
|
|
NULL
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
static const char *help_msg_fc[] = {
|
|
|
|
|
"Usage: fc", "<flagname> [color]", " # List colors with 'ecs'",
|
|
|
|
|
"fc", " flagname", "Get current color for given flagname",
|
|
|
|
|
"fc", " flagname color", "Set color to a flag",
|
|
|
|
|
NULL
|
|
|
|
|
};
|
2017-12-20 03:19:30 +05:30
|
|
|
|
static const char *help_msg_fd[] = {
|
|
|
|
|
"Usage: fd[d]", " [offset|flag|expression]", " # Describe flags",
|
|
|
|
|
"fd", " $$" , "# describe flag + delta for given offset",
|
2018-01-12 09:47:42 +01:00
|
|
|
|
"fd.", " $$", "# check flags in current address (no delta)",
|
2017-12-20 03:19:30 +05:30
|
|
|
|
"fdd", " $$", "# describe flag without space restrictions",
|
|
|
|
|
"fdw", " [string]", "# filter closest flag by string for current offset",
|
2019-04-19 22:45:36 +02:00
|
|
|
|
NULL
|
2017-12-20 03:19:30 +05:30
|
|
|
|
};
|
2017-07-26 06:14:06 -07:00
|
|
|
|
|
|
|
|
|
static const char *help_msg_fs[] = {
|
|
|
|
|
"Usage: fs","[*] [+-][flagspace|addr]", " # Manage flagspaces",
|
|
|
|
|
"fs","","display flagspaces",
|
|
|
|
|
"fs*","","display flagspaces as r2 commands",
|
|
|
|
|
"fsj","","display flagspaces in JSON",
|
|
|
|
|
"fs"," *","select all flagspaces",
|
|
|
|
|
"fs"," flagspace","select flagspace or create if it doesn't exist",
|
|
|
|
|
"fs","-flagspace","remove flagspace",
|
|
|
|
|
"fs","-*","remove all flagspaces",
|
|
|
|
|
"fs","+foo","push previous flagspace and set",
|
|
|
|
|
"fs","-","pop to the previous flagspace",
|
|
|
|
|
"fs","-.","remove the current flagspace",
|
2017-10-23 12:54:03 +02:00
|
|
|
|
"fsq","", "list flagspaces in quiet mode",
|
2017-07-26 06:14:06 -07:00
|
|
|
|
"fsm"," [addr]","move flags at given address to the current flagspace",
|
|
|
|
|
"fss","","display flagspaces stack",
|
|
|
|
|
"fss*","","display flagspaces stack in r2 commands",
|
|
|
|
|
"fssj","","display flagspaces stack in JSON",
|
|
|
|
|
"fsr"," newname","rename selected flagspace",
|
|
|
|
|
NULL
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
static const char *help_msg_fz[] = {
|
|
|
|
|
"Usage: f", "[?|-name| name] [@addr]", " # Manage flagzones",
|
|
|
|
|
" fz", " math", "add new flagzone named 'math'",
|
|
|
|
|
" fz-", "math", "remove the math flagzone",
|
|
|
|
|
" fz-", "*", "remove all flagzones",
|
|
|
|
|
" fz.", "", "show around flagzone context",
|
|
|
|
|
" fz:", "", "show what's in scr.flagzone for visual",
|
|
|
|
|
" fz*", "", "dump into r2 commands, for projects",
|
2017-09-12 02:05:24 -07:00
|
|
|
|
NULL
|
2017-07-26 06:14:06 -07:00
|
|
|
|
};
|
|
|
|
|
|
2017-07-27 05:52:17 -07:00
|
|
|
|
static void cmd_flag_init(RCore *core) {
|
|
|
|
|
DEFINE_CMD_DESCRIPTOR (core, f);
|
|
|
|
|
DEFINE_CMD_DESCRIPTOR (core, fc);
|
2017-12-20 03:19:30 +05:30
|
|
|
|
DEFINE_CMD_DESCRIPTOR (core, fd);
|
2017-07-27 05:52:17 -07:00
|
|
|
|
DEFINE_CMD_DESCRIPTOR (core, fs);
|
|
|
|
|
DEFINE_CMD_DESCRIPTOR (core, fz);
|
2017-07-26 06:14:06 -07:00
|
|
|
|
}
|
|
|
|
|
|
2019-05-18 11:47:00 +02:00
|
|
|
|
static bool listFlag(RFlagItem *flag, void *user) {
|
|
|
|
|
r_list_append (user, flag);
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static size_t countMatching (const char *a, const char *b) {
|
|
|
|
|
size_t matches = 0;
|
|
|
|
|
for (; *a && *b; a++, b++) {
|
|
|
|
|
if (*a != *b) {
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
matches++;
|
|
|
|
|
}
|
|
|
|
|
return matches;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static const char *__isOnlySon(RCore *core, RList *flags, const char *kw) {
|
|
|
|
|
RListIter *iter;
|
|
|
|
|
RFlagItem *f;
|
|
|
|
|
|
|
|
|
|
size_t count = 0;
|
|
|
|
|
char *fname = NULL;
|
|
|
|
|
r_list_foreach (flags, iter, f) {
|
|
|
|
|
if (!strncmp (f->name, kw, strlen (kw))) {
|
|
|
|
|
count++;
|
|
|
|
|
if (count > 1) {
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
fname = f->name;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return fname;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static RList *__childrenFlagsOf(RCore *core, RList *flags, const char *prefix) {
|
|
|
|
|
RList *list = r_list_newf (free);
|
|
|
|
|
RListIter *iter, *iter2;
|
|
|
|
|
RFlagItem *f, *f2;
|
|
|
|
|
char *fn;
|
|
|
|
|
|
|
|
|
|
const size_t prefix_len = strlen (prefix);
|
|
|
|
|
r_list_foreach (flags, iter, f) {
|
|
|
|
|
if (prefix_len > 0 && strncmp (f->name, prefix, prefix_len)) {
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
if (prefix_len > strlen (f->name)) {
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
if (r_cons_is_breaked ()) {
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
const char *name = f->name;
|
|
|
|
|
int name_len = strlen (name);
|
|
|
|
|
r_list_foreach (flags, iter2, f2) {
|
|
|
|
|
if (prefix_len > strlen (f2->name)) {
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
if (prefix_len > 0 && strncmp (f2->name, prefix, prefix_len)) {
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
int matching = countMatching (name, f2->name);
|
|
|
|
|
if (matching < prefix_len || matching == name_len) {
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
if (matching > name_len) {
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
if (matching < name_len) {
|
|
|
|
|
name_len = matching;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
char *kw = r_str_ndup (name, name_len + 1);
|
|
|
|
|
const int kw_len = strlen (kw);
|
|
|
|
|
const char *only = __isOnlySon (core, flags, kw);
|
|
|
|
|
if (only) {
|
|
|
|
|
free (kw);
|
|
|
|
|
kw = strdup (only);
|
|
|
|
|
} else {
|
|
|
|
|
const char *fname = NULL;
|
|
|
|
|
size_t fname_len = 0;
|
|
|
|
|
r_list_foreach (flags, iter2, f2) {
|
|
|
|
|
if (strncmp (f2->name, kw, kw_len)) {
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
if (fname) {
|
|
|
|
|
int matching = countMatching (fname, f2->name);
|
|
|
|
|
if (fname_len) {
|
|
|
|
|
if (matching < fname_len) {
|
|
|
|
|
fname_len = matching;
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
fname_len = matching;
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
fname = f2->name;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (fname_len > 0) {
|
|
|
|
|
free (kw);
|
|
|
|
|
kw = r_str_ndup (fname, fname_len);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool found = false;
|
|
|
|
|
r_list_foreach (list, iter2, fn) {
|
|
|
|
|
if (!strcmp (fn, kw)) {
|
|
|
|
|
found = true;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (found) {
|
|
|
|
|
free (kw);
|
|
|
|
|
} else {
|
|
|
|
|
if (strcmp (prefix, kw)) {
|
|
|
|
|
r_list_append (list, kw);
|
|
|
|
|
} else {
|
|
|
|
|
free (kw);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return list;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void __printRecursive (RCore *core, RList *list, const char *prefix, int mode, int depth);
|
|
|
|
|
|
|
|
|
|
static void __printRecursive (RCore *core, RList *flags, const char *prefix, int mode, int depth) {
|
|
|
|
|
char *fn;
|
|
|
|
|
RListIter *iter;
|
|
|
|
|
const int prefix_len = strlen (prefix);
|
|
|
|
|
// eprintf ("# fg %s\n", prefix);
|
|
|
|
|
if (mode == '*' && !*prefix) {
|
|
|
|
|
r_cons_printf ("agn root\n");
|
|
|
|
|
}
|
|
|
|
|
if (r_flag_get (core->flags, prefix)) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
RList *children = __childrenFlagsOf (core, flags, prefix);
|
|
|
|
|
r_list_foreach (children, iter, fn) {
|
|
|
|
|
if (!strcmp (fn, prefix)) {
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
if (mode == '*') {
|
|
|
|
|
r_cons_printf ("agn %s %s\n", fn, fn + prefix_len);
|
|
|
|
|
r_cons_printf ("age %s %s\n", *prefix? prefix: "root", fn);
|
|
|
|
|
} else {
|
|
|
|
|
r_cons_printf ("%s %s\n", r_str_pad (' ', prefix_len), fn + prefix_len);
|
|
|
|
|
}
|
|
|
|
|
//r_cons_printf (".fg %s\n", fn);
|
|
|
|
|
__printRecursive (core, flags, fn, mode, depth+1);
|
|
|
|
|
}
|
|
|
|
|
r_list_free (children);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void __flag_graph (RCore *core, const char *input, int mode) {
|
|
|
|
|
RList *flags = r_list_newf (NULL);
|
|
|
|
|
r_flag_foreach_space (core->flags, r_flag_space_cur (core->flags), listFlag, flags);
|
|
|
|
|
__printRecursive (core, flags, input, mode, 0);
|
|
|
|
|
r_list_free (flags);
|
|
|
|
|
}
|
|
|
|
|
|
2019-05-10 10:13:54 +02:00
|
|
|
|
static void spaces_list(RSpaces *sp, int mode) {
|
|
|
|
|
RSpaceIter it;
|
|
|
|
|
RSpace *s;
|
|
|
|
|
const RSpace *cur = r_spaces_current (sp);
|
|
|
|
|
PJ *pj = NULL;
|
|
|
|
|
if (mode == 'j') {
|
|
|
|
|
pj = pj_new ();
|
|
|
|
|
pj_a (pj);
|
|
|
|
|
}
|
|
|
|
|
r_spaces_foreach (sp, it, s) {
|
|
|
|
|
int count = r_spaces_count (sp, s->name);
|
|
|
|
|
if (mode == 'j') {
|
|
|
|
|
pj_o (pj);
|
|
|
|
|
pj_ks (pj, "name", s->name);
|
|
|
|
|
pj_ki (pj, "count", count);
|
|
|
|
|
pj_kb (pj, "selected", cur == s);
|
|
|
|
|
pj_end (pj);
|
|
|
|
|
} else if (mode == 'q') {
|
|
|
|
|
r_cons_printf ("%s\n", s->name);
|
|
|
|
|
} else if (mode == '*') {
|
|
|
|
|
r_cons_printf ("%s %s\n", sp->name, s->name);
|
|
|
|
|
} else {
|
|
|
|
|
r_cons_printf ("%5d %c %s\n", count, (!cur || cur == s)? '*': '.',
|
|
|
|
|
s->name);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (mode == '*' && r_spaces_current (sp)) {
|
|
|
|
|
r_cons_printf ("%s %s # current\n", sp->name, r_spaces_current_name (sp));
|
|
|
|
|
}
|
|
|
|
|
if (mode == 'j') {
|
|
|
|
|
pj_end (pj);
|
|
|
|
|
r_cons_printf ("%s\n", pj_string (pj));
|
|
|
|
|
pj_free (pj);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2016-10-06 02:40:26 +02:00
|
|
|
|
static void cmd_fz(RCore *core, const char *input) {
|
|
|
|
|
switch (*input) {
|
2019-05-09 17:49:27 +03:00
|
|
|
|
case '?': // "fz?"
|
2017-07-26 06:14:06 -07:00
|
|
|
|
r_core_cmd_help (core, help_msg_fz);
|
2016-10-06 02:40:26 +02:00
|
|
|
|
break;
|
2019-05-09 17:49:27 +03:00
|
|
|
|
case '.': // "fz."
|
2016-10-06 02:40:26 +02:00
|
|
|
|
{
|
2019-04-11 06:48:22 +02:00
|
|
|
|
const char *a = NULL, *b = NULL;
|
2016-10-06 02:40:26 +02:00
|
|
|
|
r_flag_zone_around (core->flags, core->offset, &a, &b);
|
2019-04-11 06:48:22 +02:00
|
|
|
|
r_cons_printf ("%s %s\n", a?a:"~", b?b:"~");
|
2016-10-06 02:40:26 +02:00
|
|
|
|
}
|
|
|
|
|
break;
|
2019-05-09 17:49:27 +03:00
|
|
|
|
case ':': // "fz:"
|
2016-10-06 02:40:26 +02:00
|
|
|
|
{
|
|
|
|
|
const char *a, *b;
|
|
|
|
|
int a_len = 0;
|
|
|
|
|
int w = r_cons_get_size (NULL);
|
|
|
|
|
r_flag_zone_around (core->flags, core->offset, &a, &b);
|
|
|
|
|
if (a) {
|
|
|
|
|
r_cons_printf ("[<< %s]", a);
|
|
|
|
|
a_len = strlen (a) + 4;
|
|
|
|
|
}
|
|
|
|
|
int padsize = (w / 2) - a_len;
|
|
|
|
|
int title_size = 12;
|
|
|
|
|
if (a || b) {
|
|
|
|
|
char *title = r_str_newf ("[ 0x%08"PFMT64x" ]", core->offset);
|
|
|
|
|
title_size = strlen (title);
|
|
|
|
|
padsize -= strlen (title) / 2;
|
|
|
|
|
const char *halfpad = r_str_pad (' ', padsize);
|
|
|
|
|
r_cons_printf ("%s%s", halfpad, title);
|
|
|
|
|
free (title);
|
|
|
|
|
}
|
|
|
|
|
if (b) {
|
|
|
|
|
padsize = (w / 2) - title_size - strlen (b) - 4;
|
|
|
|
|
const char *halfpad = padsize > 1? r_str_pad (' ', padsize): "";
|
|
|
|
|
r_cons_printf ("%s[%s >>]", halfpad, b);
|
|
|
|
|
}
|
|
|
|
|
if (a || b) {
|
|
|
|
|
r_cons_newline();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case ' ':
|
2020-03-02 21:39:37 +01:00
|
|
|
|
r_flag_zone_add (core->flags, r_str_trim_head_ro (input + 1), core->offset);
|
2016-10-06 02:40:26 +02:00
|
|
|
|
break;
|
|
|
|
|
case '-':
|
|
|
|
|
if (input[1] == '*') {
|
|
|
|
|
r_flag_zone_reset (core->flags);
|
|
|
|
|
} else {
|
|
|
|
|
r_flag_zone_del (core->flags, input + 1);
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case '*':
|
|
|
|
|
r_flag_zone_list (core->flags, '*');
|
|
|
|
|
break;
|
|
|
|
|
case 0:
|
|
|
|
|
r_flag_zone_list (core->flags, 0);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2019-01-14 14:15:12 +01:00
|
|
|
|
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;
|
|
|
|
|
}
|
2014-10-21 04:39:37 +02:00
|
|
|
|
|
2017-01-24 00:43:57 +01:00
|
|
|
|
static void flagbars(RCore *core, const char *glob) {
|
2014-10-21 04:39:37 +02:00
|
|
|
|
int cols = r_cons_get_size (NULL);
|
2017-01-24 00:43:57 +01:00
|
|
|
|
cols -= 80;
|
|
|
|
|
if (cols < 0) {
|
|
|
|
|
cols += 80;
|
2014-10-21 04:39:37 +02:00
|
|
|
|
}
|
2019-01-14 14:15:12 +01:00
|
|
|
|
|
|
|
|
|
struct flagbar_t u = { .core = core, .cols = cols };
|
2019-08-17 20:14:20 +05:30
|
|
|
|
r_flag_foreach_space_glob (core->flags, glob, r_flag_space_cur (core->flags), flagbar_foreach, &u);
|
2019-01-14 14:15:12 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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;
|
2013-09-24 00:43:31 +02:00
|
|
|
|
}
|
2019-01-14 14:15:12 +01:00
|
|
|
|
return true;
|
2013-09-24 00:43:31 +02:00
|
|
|
|
}
|
|
|
|
|
|
2017-11-23 14:34:07 +01:00
|
|
|
|
static int flag_to_flag(RCore *core, const char *glob) {
|
2019-01-14 14:15:12 +01:00
|
|
|
|
r_return_val_if_fail (glob, 0);
|
2020-03-02 21:39:37 +01:00
|
|
|
|
glob = r_str_trim_head_ro (glob);
|
2019-01-14 14:15:12 +01:00
|
|
|
|
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;
|
2017-11-23 14:34:07 +01:00
|
|
|
|
}
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
2020-01-18 17:40:24 +01:00
|
|
|
|
typedef struct {
|
|
|
|
|
RTable *t;
|
|
|
|
|
} FlagTableData;
|
|
|
|
|
|
|
|
|
|
static bool __tableItemCallback(RFlagItem *flag, void *user) {
|
|
|
|
|
FlagTableData *ftd = user;
|
2020-01-18 18:09:30 +01:00
|
|
|
|
if (!R_STR_ISEMPTY (flag->name)) {
|
2020-01-18 17:40:24 +01:00
|
|
|
|
RTable *t = ftd->t;
|
|
|
|
|
const char *spaceName = (flag->space && flag->space->name)? flag->space->name: "";
|
|
|
|
|
const char *addr = sdb_fmt ("0x%08"PFMT64x, flag->offset);
|
|
|
|
|
r_table_add_row (t, addr, sdb_fmt ("%d", flag->size), spaceName, flag->name, NULL);
|
|
|
|
|
}
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void cmd_flag_table(RCore *core, const char *input) {
|
|
|
|
|
const char fmt = *input++;
|
|
|
|
|
const char *q = input;
|
|
|
|
|
FlagTableData ftd = {0};
|
|
|
|
|
RTable *t = r_core_table (core);
|
|
|
|
|
ftd.t = t;
|
|
|
|
|
RTableColumnType *typeString = r_table_type ("string");
|
|
|
|
|
RTableColumnType *typeNumber = r_table_type ("number");
|
|
|
|
|
r_table_add_column (t, typeNumber, "addr", 0);
|
|
|
|
|
r_table_add_column (t, typeNumber, "size", 0);
|
|
|
|
|
r_table_add_column (t, typeString, "space", 0);
|
|
|
|
|
r_table_add_column (t, typeString, "name", 0);
|
|
|
|
|
|
|
|
|
|
RSpace *curSpace = r_flag_space_cur (core->flags);
|
|
|
|
|
r_flag_foreach_space (core->flags, curSpace, __tableItemCallback, &ftd);
|
|
|
|
|
if (r_table_query (t, q)) {
|
|
|
|
|
char *s = (fmt == 'j')
|
|
|
|
|
? r_table_tojson (t)
|
|
|
|
|
: r_table_tofancystring (t);
|
|
|
|
|
// char *s = r_table_tostring (t);
|
|
|
|
|
r_cons_printf ("%s\n", s);
|
|
|
|
|
free (s);
|
|
|
|
|
}
|
|
|
|
|
r_table_free (t);
|
|
|
|
|
}
|
|
|
|
|
|
2019-09-02 00:37:20 +02:00
|
|
|
|
static void cmd_flag_tags(RCore *core, const char *input) {
|
2018-05-11 17:18:36 +02:00
|
|
|
|
char mode = input[1];
|
2018-05-14 03:00:36 +02:00
|
|
|
|
for (; *input && !IS_WHITESPACE (*input); input++) {}
|
2018-05-11 17:18:36 +02:00
|
|
|
|
char *inp = strdup (input);
|
2019-06-16 20:58:40 +02:00
|
|
|
|
char *arg = inp;
|
|
|
|
|
r_str_trim (arg);
|
2018-05-26 18:12:13 +02:00
|
|
|
|
if (!*arg && !mode) {
|
2018-05-11 17:18:36 +02:00
|
|
|
|
const char *tag;
|
|
|
|
|
RListIter *iter;
|
2019-04-23 03:27:58 +02:00
|
|
|
|
RList *list = r_flag_tags_list (core->flags, NULL);
|
2018-05-11 17:18:36 +02:00
|
|
|
|
r_list_foreach (list, iter, tag) {
|
|
|
|
|
r_cons_printf ("%s\n", tag);
|
|
|
|
|
}
|
|
|
|
|
r_list_free (list);
|
|
|
|
|
free (inp);
|
2018-05-11 04:39:08 +02:00
|
|
|
|
return;
|
|
|
|
|
}
|
2018-05-26 18:12:13 +02:00
|
|
|
|
if (mode == '?') {
|
2019-04-19 14:19:19 +02:00
|
|
|
|
eprintf ("Usage: ft[?ln] [k] [v ...]\n");
|
2018-05-11 17:18:36 +02:00
|
|
|
|
eprintf (" ft tag strcpy strlen ... # set words for the 'string' tag\n");
|
|
|
|
|
eprintf (" ft tag # get offsets of all matching flags\n");
|
|
|
|
|
eprintf (" ft # list all tags\n");
|
|
|
|
|
eprintf (" ftn tag # get matching flagnames fot given tag\n");
|
2019-04-19 16:54:53 +02:00
|
|
|
|
eprintf (" ftw # flag tags within this file\n");
|
2019-04-23 03:27:58 +02:00
|
|
|
|
eprintf (" ftj # list all flagtags in JSON format\n");
|
|
|
|
|
eprintf (" ft* # list all flagtags in r2 commands\n");
|
2018-05-11 17:18:36 +02:00
|
|
|
|
free (inp);
|
2018-05-11 04:39:08 +02:00
|
|
|
|
return;
|
|
|
|
|
}
|
2019-04-19 16:54:53 +02:00
|
|
|
|
if (mode == 'w') { // "ftw"
|
2019-04-19 14:19:19 +02:00
|
|
|
|
const char *tag;
|
|
|
|
|
RListIter *iter;
|
2019-04-23 03:27:58 +02:00
|
|
|
|
RList *list = r_flag_tags_list (core->flags, NULL);
|
2019-04-19 14:19:19 +02:00
|
|
|
|
r_list_foreach (list, iter, tag) {
|
|
|
|
|
r_cons_printf ("%s:\n", tag);
|
|
|
|
|
r_core_cmdf (core, "ftn %s", tag);
|
|
|
|
|
}
|
|
|
|
|
r_list_free (list);
|
|
|
|
|
free (inp);
|
|
|
|
|
return;
|
|
|
|
|
}
|
2019-04-23 03:27:58 +02:00
|
|
|
|
if (mode == '*') {
|
|
|
|
|
RListIter *iter;
|
|
|
|
|
const char *tag;
|
|
|
|
|
RList *list = r_flag_tags_list (core->flags, NULL);
|
|
|
|
|
r_list_foreach (list, iter, tag) {
|
|
|
|
|
const char *flags = sdb_get (core->flags->tags, sdb_fmt ("tag.%s", tag), NULL);
|
|
|
|
|
r_cons_printf ("ft %s %s\n", tag, flags);
|
|
|
|
|
}
|
|
|
|
|
r_list_free (list);
|
2020-01-14 19:57:34 +08:00
|
|
|
|
free (inp);
|
2019-04-23 03:27:58 +02:00
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
if (mode == 'j') { // "ftj"
|
|
|
|
|
RListIter *iter, *iter2;
|
|
|
|
|
const char *tag, *flg;
|
|
|
|
|
PJ *pj = pj_new ();
|
|
|
|
|
pj_o (pj);
|
|
|
|
|
RList *list = r_flag_tags_list (core->flags, NULL);
|
|
|
|
|
r_list_foreach (list, iter, tag) {
|
|
|
|
|
pj_k (pj, tag);
|
|
|
|
|
pj_a (pj);
|
|
|
|
|
RList *flags = r_flag_tags_list (core->flags, tag);
|
|
|
|
|
r_list_foreach (flags, iter2, flg) {
|
|
|
|
|
pj_s (pj, flg);
|
|
|
|
|
}
|
|
|
|
|
pj_end (pj);
|
2020-01-17 12:58:29 +08:00
|
|
|
|
r_list_free (flags);
|
2019-04-23 03:27:58 +02:00
|
|
|
|
}
|
|
|
|
|
pj_end (pj);
|
|
|
|
|
r_list_free (list);
|
2020-01-14 19:57:34 +08:00
|
|
|
|
free (inp);
|
2019-04-23 03:27:58 +02:00
|
|
|
|
r_cons_printf ("%s\n", pj_string (pj));
|
|
|
|
|
pj_free (pj);
|
|
|
|
|
return;
|
|
|
|
|
}
|
2018-05-11 04:39:08 +02:00
|
|
|
|
char *arg1 = strchr (arg, ' ');
|
|
|
|
|
if (arg1) {
|
|
|
|
|
*arg1 = 0;
|
2020-03-02 21:39:37 +01:00
|
|
|
|
const char *a1 = r_str_trim_head_ro (arg1 + 1);
|
2018-05-11 04:39:08 +02:00
|
|
|
|
r_flag_tags_set (core->flags, arg, a1);
|
|
|
|
|
} else {
|
|
|
|
|
RListIter *iter;
|
|
|
|
|
RFlagItem *flag;
|
|
|
|
|
RList *flags = r_flag_tags_get (core->flags, arg);
|
2018-05-11 17:18:36 +02:00
|
|
|
|
switch (mode) {
|
|
|
|
|
case 'n':
|
|
|
|
|
r_list_foreach (flags, iter, flag) {
|
|
|
|
|
// r_cons_printf ("0x%08"PFMT64x"\n", flag->offset);
|
|
|
|
|
r_cons_printf ("0x%08"PFMT64x" %s\n", flag->offset, flag->name);
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
r_list_foreach (flags, iter, flag) {
|
|
|
|
|
r_cons_printf ("0x%08"PFMT64x"\n", flag->offset);
|
|
|
|
|
}
|
|
|
|
|
break;
|
2018-05-11 04:39:08 +02:00
|
|
|
|
}
|
|
|
|
|
}
|
2018-05-11 17:18:36 +02:00
|
|
|
|
free (inp);
|
2018-05-11 04:39:08 +02:00
|
|
|
|
}
|
|
|
|
|
|
2019-01-14 14:15:12 +01:00
|
|
|
|
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;
|
|
|
|
|
}
|
|
|
|
|
|
2017-12-02 02:11:22 +01:00
|
|
|
|
static void flag_ordinals(RCore *core, const char *str) {
|
2020-03-02 21:39:37 +01:00
|
|
|
|
const char *glob = r_str_trim_head_ro (str);
|
2017-12-02 02:11:22 +01:00
|
|
|
|
char *pfx = strdup (glob);
|
|
|
|
|
char *p = strchr (pfx, '*');
|
|
|
|
|
if (p) {
|
|
|
|
|
*p = 0;
|
|
|
|
|
}
|
2019-01-14 14:15:12 +01:00
|
|
|
|
|
|
|
|
|
struct rename_flag_t u = { .core = core, .pfx = pfx, .count = 0 };
|
|
|
|
|
r_flag_foreach_glob (core->flags, glob, rename_flag_ordinal, &u);
|
|
|
|
|
free (pfx);
|
2017-12-02 02:11:22 +01:00
|
|
|
|
}
|
|
|
|
|
|
2017-12-20 03:19:30 +05:30
|
|
|
|
static int cmpflag(const void *_a, const void *_b) {
|
|
|
|
|
const RFlagItem *flag1 = _a , *flag2 = _b;
|
|
|
|
|
return (flag1->offset - flag2->offset);
|
|
|
|
|
}
|
|
|
|
|
|
2019-01-14 14:15:12 +01:00
|
|
|
|
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;
|
|
|
|
|
}
|
|
|
|
|
|
2019-02-03 16:06:45 +01:00
|
|
|
|
static void print_space_stack(RFlag *f, int ordinal, const char *name, bool selected, PJ *pj, int mode) {
|
|
|
|
|
bool first = ordinal == 0;
|
|
|
|
|
switch (mode) {
|
|
|
|
|
case 'j': {
|
|
|
|
|
char *ename = r_str_escape (name);
|
|
|
|
|
if (!ename) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pj_o (pj);
|
|
|
|
|
pj_ki (pj, "ordinal", ordinal);
|
|
|
|
|
pj_ks (pj, "name", ename);
|
|
|
|
|
pj_kb (pj, "selected", selected);
|
|
|
|
|
pj_end (pj);
|
|
|
|
|
free (ename);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
case '*': {
|
|
|
|
|
const char *fmt = first? "fs %s\n": "fs+%s\n";
|
|
|
|
|
r_cons_printf (fmt, name);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
default:
|
|
|
|
|
r_cons_printf ("%-2d %s%s\n", ordinal, name, selected? " (selected)": "");
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int flag_space_stack_list(RFlag *f, int mode) {
|
|
|
|
|
RListIter *iter;
|
|
|
|
|
char *space;
|
|
|
|
|
int i = 0;
|
|
|
|
|
PJ *pj = NULL;
|
|
|
|
|
if (mode == 'j') {
|
|
|
|
|
pj = pj_new ();
|
|
|
|
|
pj_a (pj);
|
|
|
|
|
}
|
|
|
|
|
r_list_foreach (f->spaces.spacestack, iter, space) {
|
|
|
|
|
print_space_stack (f, i++, space, false, pj, mode);
|
|
|
|
|
}
|
|
|
|
|
const char *cur_name = r_flag_space_cur_name (f);
|
|
|
|
|
print_space_stack (f, i++, cur_name, true, pj, mode);
|
|
|
|
|
if (mode == 'j') {
|
|
|
|
|
pj_end (pj);
|
|
|
|
|
r_cons_printf ("%s\n", pj_string (pj));
|
|
|
|
|
pj_free (pj);
|
|
|
|
|
}
|
|
|
|
|
return i;
|
|
|
|
|
}
|
|
|
|
|
|
2012-02-27 02:40:27 +01:00
|
|
|
|
static int cmd_flag(void *data, const char *input) {
|
2015-02-03 01:11:33 +01:00
|
|
|
|
static int flagenum = 0;
|
2012-02-27 02:40:27 +01:00
|
|
|
|
RCore *core = (RCore *)data;
|
|
|
|
|
ut64 off = core->offset;
|
2012-11-13 03:25:07 +01:00
|
|
|
|
char *ptr, *str = NULL;
|
2015-07-13 11:21:21 +02:00
|
|
|
|
RFlagItem *item;
|
2014-09-01 02:24:38 +02:00
|
|
|
|
char *name = NULL;
|
2012-11-13 03:25:07 +01:00
|
|
|
|
st64 base;
|
2012-02-27 02:40:27 +01:00
|
|
|
|
|
2013-06-30 02:45:33 +02:00
|
|
|
|
// TODO: off+=cursor
|
2016-07-03 21:57:00 +02:00
|
|
|
|
if (*input) {
|
|
|
|
|
str = strdup (input + 1);
|
|
|
|
|
}
|
2015-04-12 00:44:49 +02:00
|
|
|
|
rep:
|
2012-02-27 02:40:27 +01:00
|
|
|
|
switch (*input) {
|
2017-11-23 14:34:07 +01:00
|
|
|
|
case 'f': // "ff"
|
2017-11-23 17:08:05 +01:00
|
|
|
|
if (input[1] == 's') { // "ffs"
|
|
|
|
|
int delta = flag_to_flag (core, input + 2);
|
|
|
|
|
if (delta > 0) {
|
|
|
|
|
r_cons_printf ("0x%08"PFMT64x"\n", core->offset + delta);
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
r_cons_printf ("%d\n", flag_to_flag (core, input + 1));
|
|
|
|
|
}
|
2017-11-23 14:34:07 +01:00
|
|
|
|
break;
|
|
|
|
|
case 'e': // "fe"
|
2015-02-03 01:11:33 +01:00
|
|
|
|
switch (input[1]) {
|
|
|
|
|
case ' ':
|
2017-11-23 14:34:07 +01:00
|
|
|
|
ptr = r_str_newf ("%s.%d", input + 2, flagenum);
|
|
|
|
|
(void)r_flag_set (core->flags, ptr, core->offset, 1);
|
2015-02-03 01:11:33 +01:00
|
|
|
|
flagenum++;
|
|
|
|
|
free (ptr);
|
|
|
|
|
break;
|
|
|
|
|
case '-':
|
|
|
|
|
flagenum = 0;
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
eprintf ("|Usage: fe[-| name] @@= 1 2 3 4\n");
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
break;
|
2014-10-21 04:39:37 +02:00
|
|
|
|
case '=': // "f="
|
|
|
|
|
switch (input[1]) {
|
2017-01-24 00:43:57 +01:00
|
|
|
|
case ' ':
|
|
|
|
|
flagbars (core, input + 2);
|
2014-10-21 04:39:37 +02:00
|
|
|
|
break;
|
2017-01-24 00:43:57 +01:00
|
|
|
|
case 0:
|
|
|
|
|
flagbars (core, NULL);
|
2014-10-21 04:39:37 +02:00
|
|
|
|
break;
|
|
|
|
|
default:
|
2017-01-24 00:43:57 +01:00
|
|
|
|
case '?':
|
|
|
|
|
eprintf ("Usage: f= [glob] to grep for matching flag names\n");
|
2014-10-21 04:39:37 +02:00
|
|
|
|
break;
|
|
|
|
|
}
|
2013-09-24 00:43:31 +02:00
|
|
|
|
break;
|
2014-09-01 02:24:38 +02:00
|
|
|
|
case 'a':
|
2016-10-28 12:19:44 +02:00
|
|
|
|
if (input[1] == ' '){
|
2014-09-01 02:24:38 +02:00
|
|
|
|
RFlagItem *fi;
|
2015-02-03 15:53:21 +01:00
|
|
|
|
R_FREE (str);
|
2014-09-01 02:24:38 +02:00
|
|
|
|
str = strdup (input+2);
|
|
|
|
|
ptr = strchr (str, '=');
|
|
|
|
|
if (!ptr)
|
|
|
|
|
ptr = strchr (str, ' ');
|
|
|
|
|
if (ptr) *ptr++ = 0;
|
2020-03-02 21:39:37 +01:00
|
|
|
|
name = (char *)r_str_trim_head_ro (str);
|
|
|
|
|
ptr = (char *)r_str_trim_head_ro (ptr);
|
2014-09-01 02:24:38 +02:00
|
|
|
|
fi = r_flag_get (core->flags, name);
|
|
|
|
|
if (!fi)
|
|
|
|
|
fi = r_flag_set (core->flags, name,
|
2016-02-20 15:38:46 +01:00
|
|
|
|
core->offset, 1);
|
2014-09-01 02:24:38 +02:00
|
|
|
|
if (fi) {
|
|
|
|
|
r_flag_item_set_alias (fi, ptr);
|
|
|
|
|
} else {
|
|
|
|
|
eprintf ("Cannot find flag '%s'\n", name);
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
eprintf ("Usage: fa flagname flagalias\n");
|
|
|
|
|
}
|
|
|
|
|
break;
|
2015-10-12 14:33:52 +02:00
|
|
|
|
case 'V': // visual marks
|
|
|
|
|
switch(input[1]) {
|
|
|
|
|
case '-':
|
|
|
|
|
r_core_visual_mark_reset (core);
|
|
|
|
|
break;
|
|
|
|
|
case ' ':
|
|
|
|
|
{
|
2019-05-11 17:09:17 +09:00
|
|
|
|
const int ASCII_MAX = 127;
|
|
|
|
|
if (atoi (input+1) + ASCII_MAX + 1 < UT8_MAX) {
|
|
|
|
|
const char *arg = strchr (input+2, ' ');
|
|
|
|
|
ut64 addr = arg? r_num_math (core->num, arg): core->offset;
|
|
|
|
|
r_core_visual_mark_set (core, atoi (input+1) + ASCII_MAX + 1, addr);
|
|
|
|
|
}
|
2015-10-12 14:33:52 +02:00
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case '?':
|
|
|
|
|
eprintf ("Usage: fV[*-] [nkey] [offset]\n");
|
|
|
|
|
eprintf ("Dump/Restore visual marks (mK/'K)\n");
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
r_core_visual_mark_dump (core);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
break;
|
2016-07-03 21:57:00 +02:00
|
|
|
|
case 'm': // "fm"
|
2014-03-02 05:41:45 +01:00
|
|
|
|
r_flag_move (core->flags, core->offset, r_num_math (core->num, input+1));
|
|
|
|
|
break;
|
2016-07-03 21:57:00 +02:00
|
|
|
|
case 'R': // "fR"
|
2017-05-22 02:54:26 +02:00
|
|
|
|
switch(*str) {
|
|
|
|
|
case '\0':
|
2015-06-20 13:57:11 +02:00
|
|
|
|
eprintf ("Usage: fR [from] [to] ([mask])\n");
|
|
|
|
|
eprintf ("Example to relocate PIE flags on debugger:\n"
|
|
|
|
|
" > fR entry0 `dm~:1[1]`\n");
|
|
|
|
|
break;
|
2017-05-22 02:54:26 +02:00
|
|
|
|
case '?':
|
|
|
|
|
r_cons_println ("Usage: fR [from] [to] ([mask])");
|
|
|
|
|
r_cons_println ("Example to relocate PIE flags on debugger:\n"
|
|
|
|
|
" > fR entry0 `dm~:1[1]`");
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
{
|
|
|
|
|
char *p = strchr (str+1, ' ');
|
|
|
|
|
ut64 from, to, mask = 0xffff;
|
|
|
|
|
int ret;
|
|
|
|
|
if (p) {
|
|
|
|
|
char *q = strchr (p+1, ' ');
|
|
|
|
|
*p = 0;
|
|
|
|
|
if (q) {
|
|
|
|
|
*q = 0;
|
|
|
|
|
mask = r_num_math (core->num, q+1);
|
|
|
|
|
}
|
|
|
|
|
from = r_num_math (core->num, str+1);
|
|
|
|
|
to = r_num_math (core->num, p+1);
|
|
|
|
|
ret = r_flag_relocate (core->flags, from, mask, to);
|
|
|
|
|
eprintf ("Relocated %d flags\n", ret);
|
|
|
|
|
} else {
|
|
|
|
|
eprintf ("Usage: fR [from] [to] ([mask])\n");
|
|
|
|
|
eprintf ("Example to relocate PIE flags on debugger:\n"
|
|
|
|
|
" > fR entry0 `dm~:1[1]`\n");
|
|
|
|
|
}
|
2013-08-29 03:19:16 +02:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
break;
|
2016-07-03 21:57:00 +02:00
|
|
|
|
case 'b': // "fb"
|
2012-11-13 03:25:07 +01:00
|
|
|
|
switch (input[1]) {
|
|
|
|
|
case ' ':
|
2016-07-03 21:57:00 +02:00
|
|
|
|
free (str);
|
|
|
|
|
str = strdup (input + 2);
|
2012-11-13 03:25:07 +01:00
|
|
|
|
ptr = strchr (str, ' ');
|
|
|
|
|
if (ptr) {
|
|
|
|
|
RFlag *f = core->flags;
|
|
|
|
|
*ptr = 0;
|
|
|
|
|
base = r_num_math (core->num, str);
|
2019-01-14 14:15:12 +01:00
|
|
|
|
r_flag_foreach_glob (f, ptr + 1, adjust_offset, &base);
|
2016-07-03 21:57:00 +02:00
|
|
|
|
} else {
|
|
|
|
|
core->flags->base = r_num_math (core->num, input+1);
|
|
|
|
|
}
|
2018-11-14 22:23:20 +02:00
|
|
|
|
R_FREE (str);
|
2012-11-13 03:25:07 +01:00
|
|
|
|
break;
|
|
|
|
|
case '\0':
|
|
|
|
|
r_cons_printf ("%"PFMT64d" 0x%"PFMT64x"\n",
|
|
|
|
|
core->flags->base,
|
|
|
|
|
core->flags->base);
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
eprintf ("Usage: fb [addr] [[flags*]]\n");
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
break;
|
2017-12-10 12:53:06 +01:00
|
|
|
|
case '+': // "f+'
|
2012-02-27 02:40:27 +01:00
|
|
|
|
case ' ': {
|
2020-03-02 21:39:37 +01:00
|
|
|
|
const char *cstr = r_str_trim_head_ro (str);
|
2016-10-28 12:19:44 +02:00
|
|
|
|
char* eq = strchr (cstr, '=');
|
2019-03-31 20:02:56 -03:00
|
|
|
|
char* b64 = strstr (cstr, "base64:");
|
2016-10-28 12:19:44 +02:00
|
|
|
|
char* s = strchr (cstr, ' ');
|
2019-03-31 20:02:56 -03:00
|
|
|
|
char* s2 = NULL, *s3 = NULL;
|
|
|
|
|
char* comment = NULL;
|
|
|
|
|
bool comment_needs_free = false;
|
2012-11-13 03:25:07 +01:00
|
|
|
|
ut32 bsze = 1; //core->blocksize;
|
2019-11-05 02:53:32 +01:00
|
|
|
|
int eqdir = 0;
|
|
|
|
|
|
|
|
|
|
if (eq && eq > cstr) {
|
|
|
|
|
char *prech = eq - 1;
|
|
|
|
|
if (*prech == '+') {
|
|
|
|
|
eqdir = 1;
|
|
|
|
|
*prech = 0;
|
|
|
|
|
} else if (*prech == '-') {
|
|
|
|
|
eqdir = -1;
|
|
|
|
|
*prech = 0;
|
|
|
|
|
}
|
|
|
|
|
}
|
2019-03-31 20:02:56 -03:00
|
|
|
|
|
|
|
|
|
// Get outta here as fast as we can so we can make sure that the comment
|
|
|
|
|
// buffer used on later code can be freed properly if necessary.
|
|
|
|
|
if (*cstr == '.') {
|
|
|
|
|
input++;
|
|
|
|
|
goto rep;
|
|
|
|
|
}
|
|
|
|
|
// Check base64 padding
|
|
|
|
|
if (eq && !(b64 && eq > b64 && (eq[1] == '\0' || (eq[1] == '=' && eq[2] == '\0')))) {
|
2012-11-13 03:25:07 +01:00
|
|
|
|
*eq = 0;
|
2019-11-05 02:53:32 +01:00
|
|
|
|
ut64 arg = r_num_math (core->num, eq + 1);
|
|
|
|
|
RFlagItem *item = r_flag_get (core->flags, cstr);
|
|
|
|
|
if (eqdir && item) {
|
|
|
|
|
off = item->offset + (arg * eqdir);
|
|
|
|
|
} else {
|
|
|
|
|
off = arg;
|
|
|
|
|
}
|
2012-11-13 03:25:07 +01:00
|
|
|
|
}
|
2012-02-27 02:40:27 +01:00
|
|
|
|
if (s) {
|
|
|
|
|
*s = '\0';
|
2016-10-28 12:19:44 +02:00
|
|
|
|
s2 = strchr (s + 1, ' ');
|
2012-02-27 02:40:27 +01:00
|
|
|
|
if (s2) {
|
|
|
|
|
*s2 = '\0';
|
2016-07-03 21:57:00 +02:00
|
|
|
|
if (s2[1] && s2[2]) {
|
|
|
|
|
off = r_num_math (core->num, s2 + 1);
|
|
|
|
|
}
|
2019-03-31 20:02:56 -03:00
|
|
|
|
s3 = strchr (s2 + 1, ' ');
|
|
|
|
|
if (s3) {
|
|
|
|
|
*s3 = '\0';
|
|
|
|
|
if (!strncmp (s3 + 1, "base64:", 7)) {
|
|
|
|
|
comment = (char *) r_base64_decode_dyn (s3 + 8, -1);
|
|
|
|
|
comment_needs_free = true;
|
|
|
|
|
} else if (s3[1]) {
|
|
|
|
|
comment = s3 + 1;
|
|
|
|
|
}
|
|
|
|
|
}
|
2012-02-27 02:40:27 +01:00
|
|
|
|
}
|
2019-07-30 12:59:51 +02:00
|
|
|
|
bsze = (s[1] == '=') ? 1 : r_num_math (core->num, s + 1);
|
2012-02-27 02:40:27 +01:00
|
|
|
|
}
|
2019-03-31 20:02:56 -03:00
|
|
|
|
|
|
|
|
|
bool addFlag = true;
|
|
|
|
|
if (input[0] == '+') {
|
|
|
|
|
if ((item = r_flag_get_at (core->flags, off, false))) {
|
|
|
|
|
addFlag = false;
|
2017-03-28 14:07:26 +02:00
|
|
|
|
}
|
2019-03-31 20:02:56 -03:00
|
|
|
|
}
|
|
|
|
|
if (addFlag) {
|
|
|
|
|
item = r_flag_set (core->flags, cstr, off, bsze);
|
|
|
|
|
}
|
|
|
|
|
if (item && comment) {
|
|
|
|
|
r_flag_item_set_comment (item, comment);
|
|
|
|
|
if (comment_needs_free) {
|
|
|
|
|
free (comment);
|
2017-03-28 14:07:26 +02:00
|
|
|
|
}
|
2016-07-03 21:57:00 +02:00
|
|
|
|
}
|
2012-02-27 02:40:27 +01:00
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case '-':
|
2016-10-28 12:19:44 +02:00
|
|
|
|
if (input[1] == '-') {
|
2015-01-22 02:22:29 +01:00
|
|
|
|
r_flag_unset_all (core->flags);
|
|
|
|
|
} else if (input[1]) {
|
2020-03-02 21:39:37 +01:00
|
|
|
|
const char *flagname = r_str_trim_head_ro (input + 1);
|
2016-10-28 12:19:44 +02:00
|
|
|
|
while (*flagname==' ') {
|
|
|
|
|
flagname++;
|
|
|
|
|
}
|
2018-08-03 15:33:27 +02:00
|
|
|
|
if (*flagname == '.') {
|
2014-09-26 15:40:17 +02:00
|
|
|
|
RAnalFunction *fcn = r_anal_get_fcn_in (core->anal, off, 0);
|
2016-10-28 12:19:44 +02:00
|
|
|
|
if (fcn) {
|
2019-01-04 00:30:47 +01:00
|
|
|
|
r_anal_fcn_label_del (core->anal, fcn, flagname + 1, off);
|
2016-10-28 12:19:44 +02:00
|
|
|
|
} else {
|
|
|
|
|
eprintf ("Cannot find function at 0x%08"PFMT64x"\n", off);
|
|
|
|
|
}
|
2013-06-30 02:45:33 +02:00
|
|
|
|
} else {
|
2016-10-28 12:19:44 +02:00
|
|
|
|
if (strchr (flagname, '*')) {
|
2013-06-30 02:45:33 +02:00
|
|
|
|
r_flag_unset_glob (core->flags, flagname);
|
2016-10-28 12:19:44 +02:00
|
|
|
|
} else {
|
|
|
|
|
r_flag_unset_name (core->flags, flagname);
|
|
|
|
|
}
|
2013-06-30 02:45:33 +02:00
|
|
|
|
}
|
2016-10-28 12:19:44 +02:00
|
|
|
|
} else {
|
|
|
|
|
r_flag_unset_off (core->flags, off);
|
|
|
|
|
}
|
2012-02-27 02:40:27 +01:00
|
|
|
|
break;
|
2013-06-26 01:44:21 +04:00
|
|
|
|
case '.':
|
2020-03-02 21:39:37 +01:00
|
|
|
|
input = r_str_trim_head_ro (input + 1) - 1;
|
2013-06-30 02:45:33 +02:00
|
|
|
|
if (input[1]) {
|
|
|
|
|
if (input[1] == '*') {
|
|
|
|
|
if (input[2] == '*') {
|
2014-09-23 09:35:37 +02:00
|
|
|
|
r_anal_fcn_labels (core->anal, NULL, 1);
|
2013-06-30 02:45:33 +02:00
|
|
|
|
} else {
|
2014-09-26 15:40:17 +02:00
|
|
|
|
RAnalFunction *fcn = r_anal_get_fcn_in (core->anal, off, 0);
|
2019-09-02 00:37:20 +02:00
|
|
|
|
if (fcn) {
|
|
|
|
|
r_anal_fcn_labels (core->anal, fcn, 1);
|
|
|
|
|
} else {
|
|
|
|
|
eprintf ("Cannot find function at 0x%08"PFMT64x"\n", off);
|
|
|
|
|
}
|
2013-06-30 02:45:33 +02:00
|
|
|
|
}
|
|
|
|
|
} else {
|
2016-04-12 00:54:45 +02:00
|
|
|
|
char *name = strdup (input + ((input[2] == ' ')? 2: 1));
|
2014-09-26 15:40:17 +02:00
|
|
|
|
RAnalFunction *fcn = r_anal_get_fcn_in (core->anal, off, 0);
|
2016-04-12 00:54:45 +02:00
|
|
|
|
if (name) {
|
|
|
|
|
char *eq = strchr (name, '=');
|
|
|
|
|
if (eq) {
|
2019-11-05 02:53:32 +01:00
|
|
|
|
*eq = 0;
|
|
|
|
|
off = r_num_math (core->num, eq + 1);
|
2016-04-12 00:54:45 +02:00
|
|
|
|
}
|
2018-01-08 03:22:26 +01:00
|
|
|
|
r_str_trim (name);
|
2016-10-20 15:02:25 +02:00
|
|
|
|
if (fcn) {
|
|
|
|
|
if (*name=='-') {
|
|
|
|
|
r_anal_fcn_label_del (core->anal, fcn, name + 1, off);
|
|
|
|
|
} else {
|
|
|
|
|
r_anal_fcn_label_set (core->anal, fcn, name, off);
|
|
|
|
|
}
|
2018-08-03 15:33:27 +02:00
|
|
|
|
} else {
|
|
|
|
|
eprintf ("Cannot find function at 0x%08"PFMT64x"\n", off);
|
|
|
|
|
}
|
2016-10-20 15:02:25 +02:00
|
|
|
|
free (name);
|
2016-04-12 00:54:45 +02:00
|
|
|
|
}
|
2013-06-30 02:45:33 +02:00
|
|
|
|
}
|
|
|
|
|
} else {
|
2014-09-26 15:40:17 +02:00
|
|
|
|
RAnalFunction *fcn = r_anal_get_fcn_in (core->anal, off, 0);
|
2018-08-03 15:33:27 +02:00
|
|
|
|
if (fcn) {
|
|
|
|
|
r_anal_fcn_labels (core->anal, fcn, 0);
|
|
|
|
|
} else {
|
|
|
|
|
eprintf ("Local flags require a function to work.");
|
|
|
|
|
}
|
2013-06-26 01:44:21 +04:00
|
|
|
|
}
|
|
|
|
|
break;
|
2015-07-09 22:20:02 +02:00
|
|
|
|
case 'l': // "fl"
|
2017-01-09 03:44:52 +01:00
|
|
|
|
if (input[1] == '?') { // "fl?"
|
|
|
|
|
eprintf ("Usage: fl[a] [flagname] [flagsize]\n");
|
2019-09-02 00:37:20 +02:00
|
|
|
|
} else if (input[1] == 'a') { // "fla"
|
2016-12-15 00:12:40 +01:00
|
|
|
|
// TODO: we can optimize this if core->flags->flags is sorted by flagitem->offset
|
|
|
|
|
char *glob = strchr (input, ' ');
|
|
|
|
|
if (glob) {
|
|
|
|
|
glob++;
|
|
|
|
|
}
|
2019-01-14 14:15:12 +01:00
|
|
|
|
r_flag_foreach_glob (core->flags, glob, find_flag_after_foreach, core->flags);
|
2016-12-15 00:12:40 +01:00
|
|
|
|
} else if (input[1] == ' ') { // "fl ..."
|
|
|
|
|
char *p, *arg = strdup (input + 2);
|
2020-03-02 21:39:37 +01:00
|
|
|
|
r_str_trim (arg);
|
2015-07-09 22:20:02 +02:00
|
|
|
|
p = strchr (arg, ' ');
|
|
|
|
|
if (p) {
|
|
|
|
|
*p++ = 0;
|
2015-07-13 11:21:21 +02:00
|
|
|
|
item = r_flag_get_i (core->flags,
|
2017-01-09 03:38:55 +01:00
|
|
|
|
r_num_math (core->num, arg));
|
2015-07-09 22:20:02 +02:00
|
|
|
|
if (item)
|
|
|
|
|
item->size = r_num_math (core->num, p);
|
|
|
|
|
} else {
|
2017-01-09 03:44:52 +01:00
|
|
|
|
if (*arg) {
|
|
|
|
|
item = r_flag_get_i (core->flags, core->offset);
|
|
|
|
|
if (item) {
|
|
|
|
|
item->size = r_num_math (core->num, arg);
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
item = r_flag_get_i (core->flags, r_num_math (core->num, arg));
|
|
|
|
|
if (item) {
|
|
|
|
|
r_cons_printf ("0x%08"PFMT64x"\n", item->size);
|
|
|
|
|
}
|
|
|
|
|
}
|
2015-07-09 22:20:02 +02:00
|
|
|
|
}
|
2015-07-13 11:21:21 +02:00
|
|
|
|
free (arg);
|
2016-12-15 00:12:40 +01:00
|
|
|
|
} else { // "fl"
|
2015-07-13 11:21:21 +02:00
|
|
|
|
item = r_flag_get_i (core->flags, core->offset);
|
2012-09-06 03:12:54 +02:00
|
|
|
|
if (item)
|
2015-03-13 21:18:25 +01:00
|
|
|
|
r_cons_printf ("0x%08"PFMT64x"\n", item->size);
|
2015-07-09 22:20:02 +02:00
|
|
|
|
}
|
2012-02-27 02:40:27 +01:00
|
|
|
|
break;
|
2012-09-28 02:20:52 +02:00
|
|
|
|
#if 0
|
|
|
|
|
case 'd':
|
|
|
|
|
if (input[1] == ' ') {
|
|
|
|
|
char cmd[128];
|
|
|
|
|
RFlagItem *item = r_flag_get_i (core->flags,
|
|
|
|
|
r_num_math (core->num, input+2));
|
|
|
|
|
if (item) {
|
|
|
|
|
r_cons_printf ("0x%08"PFMT64x"\n", item->offset);
|
|
|
|
|
snprintf (cmd, sizeof (cmd), "pD@%"PFMT64d":%"PFMT64d,
|
|
|
|
|
item->offset, item->size);
|
|
|
|
|
r_core_cmd0 (core, cmd);
|
|
|
|
|
}
|
|
|
|
|
} else eprintf ("Missing arguments\n");
|
|
|
|
|
break;
|
|
|
|
|
#endif
|
2019-03-29 16:10:59 +01:00
|
|
|
|
case 'z': // "fz"
|
2016-10-06 02:40:26 +02:00
|
|
|
|
cmd_fz (core, input + 1);
|
|
|
|
|
break;
|
2012-09-28 02:20:52 +02:00
|
|
|
|
case 'x':
|
|
|
|
|
if (input[1] == ' ') {
|
|
|
|
|
char cmd[128];
|
|
|
|
|
RFlagItem *item = r_flag_get_i (core->flags,
|
|
|
|
|
r_num_math (core->num, input+2));
|
|
|
|
|
if (item) {
|
|
|
|
|
r_cons_printf ("0x%08"PFMT64x"\n", item->offset);
|
|
|
|
|
snprintf (cmd, sizeof (cmd), "px@%"PFMT64d":%"PFMT64d,
|
|
|
|
|
item->offset, item->size);
|
|
|
|
|
r_core_cmd0 (core, cmd);
|
|
|
|
|
}
|
2016-10-06 02:40:26 +02:00
|
|
|
|
} else {
|
|
|
|
|
eprintf ("Missing arguments\n");
|
|
|
|
|
}
|
2012-09-28 02:20:52 +02:00
|
|
|
|
break;
|
2020-01-18 17:40:24 +01:00
|
|
|
|
case ',': // "f,"
|
|
|
|
|
cmd_flag_table (core, input);
|
|
|
|
|
break;
|
2018-05-11 17:18:36 +02:00
|
|
|
|
case 't': // "ft"
|
2018-05-11 04:39:08 +02:00
|
|
|
|
cmd_flag_tags (core, input);
|
|
|
|
|
break;
|
2017-10-23 12:54:03 +02:00
|
|
|
|
case 's': // "fs"
|
2012-11-13 03:25:07 +01:00
|
|
|
|
switch (input[1]) {
|
2015-04-12 21:37:21 +02:00
|
|
|
|
case '?':
|
2017-07-26 06:14:06 -07:00
|
|
|
|
r_core_cmd_help (core, help_msg_fs);
|
2015-04-13 00:43:42 -04:00
|
|
|
|
break;
|
2015-04-03 20:38:34 +02:00
|
|
|
|
case '+':
|
|
|
|
|
r_flag_space_push (core->flags, input+2);
|
|
|
|
|
break;
|
2013-03-07 23:47:41 +01:00
|
|
|
|
case 'r':
|
2016-08-24 00:23:14 +02:00
|
|
|
|
if (input[2] ==' ') {
|
2019-10-01 01:13:35 -03:00
|
|
|
|
char *newname = strdup (input + 3);
|
|
|
|
|
r_str_trim (newname);
|
|
|
|
|
r_flag_space_rename (core->flags, NULL, newname);
|
|
|
|
|
free (newname);
|
2016-08-24 00:23:14 +02:00
|
|
|
|
} else {
|
|
|
|
|
eprintf ("Usage: fsr [newname]\n");
|
|
|
|
|
}
|
2013-03-07 23:47:41 +01:00
|
|
|
|
break;
|
2017-05-02 05:46:43 +02:00
|
|
|
|
case 's':
|
2019-02-03 16:06:45 +01:00
|
|
|
|
flag_space_stack_list (core->flags, input[2]);
|
2017-05-02 05:46:43 +02:00
|
|
|
|
break;
|
2015-01-22 02:22:29 +01:00
|
|
|
|
case '-':
|
2015-07-17 11:10:28 +02:00
|
|
|
|
switch (input[2]) {
|
|
|
|
|
case '*':
|
|
|
|
|
r_flag_space_unset (core->flags, NULL);
|
|
|
|
|
break;
|
2019-02-03 16:06:45 +01:00
|
|
|
|
case '.': {
|
|
|
|
|
const RSpace *sp = r_flag_space_cur (core->flags);
|
|
|
|
|
if (sp) {
|
|
|
|
|
r_flag_space_unset (core->flags, sp->name);
|
2015-04-03 20:38:34 +02:00
|
|
|
|
}
|
2015-07-17 11:10:28 +02:00
|
|
|
|
break;
|
2019-02-03 16:06:45 +01:00
|
|
|
|
}
|
2015-07-17 11:10:28 +02:00
|
|
|
|
case 0:
|
2015-04-03 20:38:34 +02:00
|
|
|
|
r_flag_space_pop (core->flags);
|
2015-07-17 11:10:28 +02:00
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
r_flag_space_unset (core->flags, input+2);
|
|
|
|
|
break;
|
2015-01-22 02:22:29 +01:00
|
|
|
|
}
|
|
|
|
|
break;
|
2012-11-13 03:25:07 +01:00
|
|
|
|
case ' ':
|
2019-10-01 01:13:35 -03:00
|
|
|
|
{
|
|
|
|
|
char *name = strdup (input + 2);
|
|
|
|
|
r_str_trim (name);
|
|
|
|
|
r_flag_space_set (core->flags, name);
|
|
|
|
|
free (name);
|
2012-11-13 03:25:07 +01:00
|
|
|
|
break;
|
2019-10-01 01:13:35 -03:00
|
|
|
|
}
|
2012-11-13 03:25:07 +01:00
|
|
|
|
case 'm':
|
|
|
|
|
{ RFlagItem *f;
|
|
|
|
|
ut64 off = core->offset;
|
2016-08-24 00:23:14 +02:00
|
|
|
|
if (input[2] == ' ') {
|
2012-11-13 03:25:07 +01:00
|
|
|
|
off = r_num_math (core->num, input+2);
|
2016-08-24 00:23:14 +02:00
|
|
|
|
}
|
2012-11-13 03:25:07 +01:00
|
|
|
|
f = r_flag_get_i (core->flags, off);
|
|
|
|
|
if (f) {
|
2019-02-03 16:06:45 +01:00
|
|
|
|
f->space = r_flag_space_cur (core->flags);
|
2016-08-24 00:23:14 +02:00
|
|
|
|
} else {
|
|
|
|
|
eprintf ("Cannot find any flag at 0x%"PFMT64x".\n", off);
|
|
|
|
|
}
|
2012-11-13 03:25:07 +01:00
|
|
|
|
}
|
|
|
|
|
break;
|
2019-05-10 10:13:54 +02:00
|
|
|
|
case 'j':
|
|
|
|
|
case '\0':
|
|
|
|
|
case '*':
|
|
|
|
|
case 'q':
|
|
|
|
|
spaces_list (&core->flags->spaces, input[1]);
|
|
|
|
|
break;
|
2019-02-03 16:06:45 +01:00
|
|
|
|
default:
|
|
|
|
|
spaces_list (&core->flags->spaces, 0);
|
|
|
|
|
break;
|
2012-09-06 03:12:54 +02:00
|
|
|
|
}
|
2012-02-27 02:40:27 +01:00
|
|
|
|
break;
|
2019-05-18 11:47:00 +02:00
|
|
|
|
case 'g': // "fg"
|
|
|
|
|
switch (input[1]) {
|
|
|
|
|
case '*':
|
2020-03-02 21:39:37 +01:00
|
|
|
|
__flag_graph (core, r_str_trim_head_ro (input + 2), '*');
|
2019-05-18 11:47:00 +02:00
|
|
|
|
break;
|
|
|
|
|
case ' ':
|
2020-03-02 21:39:37 +01:00
|
|
|
|
__flag_graph (core, r_str_trim_head_ro (input + 2), ' ');
|
2019-05-18 11:47:00 +02:00
|
|
|
|
break;
|
|
|
|
|
case 0:
|
2020-03-02 21:39:37 +01:00
|
|
|
|
__flag_graph (core, r_str_trim_head_ro (input + 1), 0);
|
2019-05-18 11:47:00 +02:00
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
eprintf ("Usage: fg[*] ([prefix])\n");
|
|
|
|
|
break;
|
|
|
|
|
}
|
2012-08-09 18:19:00 +02:00
|
|
|
|
break;
|
2019-05-18 11:47:00 +02:00
|
|
|
|
case 'c': // "fc"
|
2016-06-17 17:17:24 -04:00
|
|
|
|
if (input[1]=='?' || input[1] != ' ') {
|
2017-07-26 06:14:06 -07:00
|
|
|
|
r_core_cmd_help (core, help_msg_fc);
|
2014-08-19 01:47:02 +02:00
|
|
|
|
} else {
|
|
|
|
|
RFlagItem *fi;
|
|
|
|
|
const char *ret;
|
2019-06-16 20:58:40 +02:00
|
|
|
|
char *arg = r_str_trim_dup (input + 2);
|
2014-08-19 01:47:02 +02:00
|
|
|
|
char *color = strchr (arg, ' ');
|
2016-10-28 12:19:44 +02:00
|
|
|
|
if (color && color[1]) {
|
2014-08-19 01:47:02 +02:00
|
|
|
|
*color++ = 0;
|
2016-10-28 12:19:44 +02:00
|
|
|
|
}
|
2014-08-19 01:47:02 +02:00
|
|
|
|
fi = r_flag_get (core->flags, arg);
|
|
|
|
|
if (fi) {
|
2019-11-07 12:46:08 +01:00
|
|
|
|
ret = r_flag_item_set_color (fi, color);
|
2014-08-19 01:47:02 +02:00
|
|
|
|
if (!color && ret)
|
2016-06-26 00:51:17 -04:00
|
|
|
|
r_cons_println (ret);
|
2014-08-19 01:47:02 +02:00
|
|
|
|
} else {
|
|
|
|
|
eprintf ("Unknown flag '%s'\n", arg);
|
|
|
|
|
}
|
|
|
|
|
free (arg);
|
|
|
|
|
}
|
2012-10-26 10:00:22 +02:00
|
|
|
|
break;
|
2019-06-20 16:41:37 +05:30
|
|
|
|
case 'C': // "fC"
|
2016-10-28 12:19:44 +02:00
|
|
|
|
if (input[1] == ' ') {
|
2012-10-26 10:00:22 +02:00
|
|
|
|
RFlagItem *item;
|
2019-03-31 20:02:56 -03:00
|
|
|
|
char *q, *p = strdup (input + 2), *dec = NULL;
|
2012-10-26 10:00:22 +02:00
|
|
|
|
q = strchr (p, ' ');
|
|
|
|
|
if (q) {
|
|
|
|
|
*q = 0;
|
|
|
|
|
item = r_flag_get (core->flags, p);
|
|
|
|
|
if (item) {
|
2019-03-31 20:02:56 -03:00
|
|
|
|
if (!strncmp (q + 1, "base64:", 7)) {
|
|
|
|
|
dec = (char *) r_base64_decode_dyn (q + 8, -1);
|
|
|
|
|
if (dec) {
|
|
|
|
|
r_flag_item_set_comment (item, dec);
|
|
|
|
|
free (dec);
|
|
|
|
|
} else {
|
|
|
|
|
eprintf ("Failed to decode base64-encoded string\n");
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
r_flag_item_set_comment (item, q + 1);
|
|
|
|
|
}
|
2016-07-03 21:57:00 +02:00
|
|
|
|
} else {
|
|
|
|
|
eprintf ("Cannot find flag with name '%s'\n", p);
|
|
|
|
|
}
|
2012-10-26 10:00:22 +02:00
|
|
|
|
} else {
|
|
|
|
|
item = r_flag_get_i (core->flags, r_num_math (core->num, p));
|
|
|
|
|
if (item && item->comment) {
|
2016-06-26 00:51:17 -04:00
|
|
|
|
r_cons_println (item->comment);
|
2016-07-03 21:57:00 +02:00
|
|
|
|
} else {
|
|
|
|
|
eprintf ("Cannot find item\n");
|
|
|
|
|
}
|
2012-10-26 10:00:22 +02:00
|
|
|
|
}
|
|
|
|
|
free (p);
|
|
|
|
|
} else eprintf ("Usage: fC [name] [comment]\n");
|
|
|
|
|
break;
|
2017-05-12 03:44:53 +02:00
|
|
|
|
case 'o': // "fo"
|
2017-09-11 15:41:07 -07:00
|
|
|
|
r_core_fortune_print_random (core);
|
2012-02-27 02:40:27 +01:00
|
|
|
|
break;
|
2017-12-02 02:11:22 +01:00
|
|
|
|
case 'O': // "fO"
|
|
|
|
|
flag_ordinals (core, input + 1);
|
|
|
|
|
break;
|
2012-02-27 02:40:27 +01:00
|
|
|
|
case 'r':
|
2019-04-19 22:45:36 +02:00
|
|
|
|
if (input[1] == ' ' && input[2]) {
|
2012-02-27 02:40:27 +01:00
|
|
|
|
RFlagItem *item;
|
2019-04-19 22:45:36 +02:00
|
|
|
|
char *old = str + 1;
|
|
|
|
|
char *new = strchr (old, ' ');
|
2012-02-27 02:40:27 +01:00
|
|
|
|
if (new) {
|
|
|
|
|
*new = 0;
|
|
|
|
|
new++;
|
|
|
|
|
item = r_flag_get (core->flags, old);
|
2015-01-30 00:22:48 +01:00
|
|
|
|
if (!item && !strncmp (old, "fcn.", 4)) {
|
|
|
|
|
item = r_flag_get (core->flags, old+4);
|
|
|
|
|
}
|
2012-02-27 02:40:27 +01:00
|
|
|
|
} else {
|
|
|
|
|
new = old;
|
|
|
|
|
item = r_flag_get_i (core->flags, core->offset);
|
|
|
|
|
}
|
2012-11-13 03:25:07 +01:00
|
|
|
|
if (item) {
|
2016-07-03 21:57:00 +02:00
|
|
|
|
if (!r_flag_rename (core->flags, item, new)) {
|
2012-11-13 03:25:07 +01:00
|
|
|
|
eprintf ("Invalid name\n");
|
2016-07-03 21:57:00 +02:00
|
|
|
|
}
|
2015-01-30 00:22:48 +01:00
|
|
|
|
} else {
|
2019-04-19 22:45:36 +02:00
|
|
|
|
eprintf ("Usage: fr [[old]] [new]\n");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case 'N':
|
|
|
|
|
if (!input[1]) {
|
|
|
|
|
RFlagItem *item = r_flag_get_i (core->flags, core->offset);
|
|
|
|
|
if (item) {
|
|
|
|
|
r_cons_printf ("%s\n", item->realname);
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
} else if (input[1] == ' ' && input[2]) {
|
|
|
|
|
RFlagItem *item;
|
|
|
|
|
char *name = str + 1;
|
|
|
|
|
char *realname = strchr (name, ' ');
|
|
|
|
|
if (realname) {
|
|
|
|
|
*realname = 0;
|
|
|
|
|
realname++;
|
|
|
|
|
item = r_flag_get (core->flags, name);
|
|
|
|
|
if (!item && !strncmp (name, "fcn.", 4)) {
|
|
|
|
|
item = r_flag_get (core->flags, name+4);
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
realname = name;
|
|
|
|
|
item = r_flag_get_i (core->flags, core->offset);
|
2015-01-30 00:22:48 +01:00
|
|
|
|
}
|
2019-04-19 22:45:36 +02:00
|
|
|
|
if (item) {
|
|
|
|
|
r_flag_item_set_realname (item, realname);
|
|
|
|
|
}
|
|
|
|
|
break;
|
2012-02-27 02:40:27 +01:00
|
|
|
|
}
|
2019-04-19 22:45:36 +02:00
|
|
|
|
eprintf ("Usage: fN [[name]] [[realname]]\n");
|
2012-02-27 02:40:27 +01:00
|
|
|
|
break;
|
2016-07-03 21:57:00 +02:00
|
|
|
|
case '\0':
|
2019-01-28 10:11:11 +01:00
|
|
|
|
case 'n': // "fn" "fnj"
|
2015-08-17 10:34:47 +02:00
|
|
|
|
case '*': // "f*"
|
|
|
|
|
case 'j': // "fj"
|
2017-10-23 12:54:03 +02:00
|
|
|
|
case 'q': // "fq"
|
2019-10-28 16:46:14 +01:00
|
|
|
|
if (input[0]) {
|
|
|
|
|
switch (input[1]) {
|
|
|
|
|
case 'j':
|
|
|
|
|
case 'q':
|
|
|
|
|
case 'n':
|
|
|
|
|
case '*':
|
|
|
|
|
input++;
|
|
|
|
|
break;
|
|
|
|
|
}
|
2019-10-28 16:08:33 +01:00
|
|
|
|
}
|
2019-10-28 16:46:14 +01:00
|
|
|
|
if (input[0] && input[1] == '.') {
|
2019-10-28 16:08:33 +01:00
|
|
|
|
const int mode = input[2];
|
|
|
|
|
const RList *list = r_flag_get_list (core->flags, core->offset);
|
|
|
|
|
PJ *pj = NULL;
|
|
|
|
|
if (mode == 'j') {
|
|
|
|
|
pj = pj_new ();
|
|
|
|
|
pj_a (pj);
|
|
|
|
|
}
|
|
|
|
|
RListIter *iter;
|
|
|
|
|
RFlagItem *item;
|
|
|
|
|
r_list_foreach (list, iter, item) {
|
|
|
|
|
switch (mode) {
|
2019-04-15 03:08:22 +02:00
|
|
|
|
case '*':
|
|
|
|
|
r_cons_printf ("f %s = 0x%08"PFMT64x"\n", item->name, item->offset);
|
|
|
|
|
break;
|
|
|
|
|
case 'j':
|
|
|
|
|
{
|
|
|
|
|
pj_o (pj);
|
|
|
|
|
pj_ks (pj, "name", item->name);
|
2019-10-28 16:46:14 +01:00
|
|
|
|
pj_ks (pj, "realname", item->realname);
|
2019-04-15 03:08:22 +02:00
|
|
|
|
pj_kn (pj, "offset", item->offset);
|
|
|
|
|
pj_kn (pj, "size", item->size);
|
|
|
|
|
pj_end (pj);
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
r_cons_printf ("%s\n", item->name);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
2019-10-28 16:08:33 +01:00
|
|
|
|
if (mode == 'j') {
|
|
|
|
|
pj_end (pj);
|
|
|
|
|
char *s = pj_drain (pj);
|
|
|
|
|
r_cons_printf ("%s\n", s);
|
|
|
|
|
free (s);
|
|
|
|
|
}
|
2019-04-15 03:08:22 +02:00
|
|
|
|
} else {
|
|
|
|
|
r_flag_list (core->flags, *input, input[0]? input + 1: "");
|
|
|
|
|
}
|
2016-07-03 21:57:00 +02:00
|
|
|
|
break;
|
|
|
|
|
case 'i': // "fi"
|
2018-08-03 15:33:27 +02:00
|
|
|
|
if (input[1] == ' ' || (input[1] && input[2] == ' ')) {
|
2020-03-02 21:39:37 +01:00
|
|
|
|
char *arg = strdup (r_str_trim_head_ro (input + 2));
|
2016-07-03 21:57:00 +02:00
|
|
|
|
if (*arg) {
|
2020-03-02 21:39:37 +01:00
|
|
|
|
arg = strdup (r_str_trim_head_ro (input + 2));
|
2016-07-03 21:57:00 +02:00
|
|
|
|
char *sp = strchr (arg, ' ');
|
|
|
|
|
if (!sp) {
|
|
|
|
|
char *newarg = r_str_newf ("%c0x%"PFMT64x" %s+0x%"PFMT64x,
|
|
|
|
|
input[1], core->offset, arg, core->offset);
|
|
|
|
|
free (arg);
|
|
|
|
|
arg = newarg;
|
|
|
|
|
} else {
|
|
|
|
|
char *newarg = r_str_newf ("%c%s", input[1], arg);
|
|
|
|
|
free (arg);
|
|
|
|
|
arg = newarg;
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
free (arg);
|
|
|
|
|
arg = r_str_newf (" 0x%"PFMT64x" 0x%"PFMT64x,
|
|
|
|
|
core->offset, core->offset + core->blocksize);
|
|
|
|
|
}
|
2018-07-02 20:06:09 +02:00
|
|
|
|
r_flag_list (core->flags, 'i', arg);
|
2016-07-03 21:57:00 +02:00
|
|
|
|
free (arg);
|
|
|
|
|
} else {
|
|
|
|
|
// XXX dupe for prev case
|
|
|
|
|
char *arg = r_str_newf (" 0x%"PFMT64x" 0x%"PFMT64x,
|
|
|
|
|
core->offset, core->offset + core->blocksize);
|
2018-07-02 20:06:09 +02:00
|
|
|
|
r_flag_list (core->flags, 'i', arg);
|
2016-07-03 21:57:00 +02:00
|
|
|
|
free (arg);
|
|
|
|
|
}
|
2012-02-27 02:40:27 +01:00
|
|
|
|
break;
|
2015-08-17 10:34:47 +02:00
|
|
|
|
case 'd': // "fd"
|
2012-02-27 02:40:27 +01:00
|
|
|
|
{
|
2017-01-24 01:41:12 +01:00
|
|
|
|
ut64 addr = core->offset;
|
2018-01-12 09:47:42 +01:00
|
|
|
|
char *arg = NULL;
|
2017-01-15 21:17:59 +01:00
|
|
|
|
RFlagItem *f = NULL;
|
2017-04-14 10:06:06 +02:00
|
|
|
|
bool strict_offset = false;
|
2012-02-27 02:40:27 +01:00
|
|
|
|
switch (input[1]) {
|
|
|
|
|
case '?':
|
2017-12-20 03:19:30 +05:30
|
|
|
|
r_core_cmd_help (core, help_msg_fd);
|
2016-07-03 21:57:00 +02:00
|
|
|
|
if (str) {
|
2014-04-30 00:57:51 +02:00
|
|
|
|
free (str);
|
2016-07-03 21:57:00 +02:00
|
|
|
|
}
|
|
|
|
|
return false;
|
2012-02-27 02:40:27 +01:00
|
|
|
|
case '\0':
|
|
|
|
|
addr = core->offset;
|
|
|
|
|
break;
|
2017-01-24 01:41:12 +01:00
|
|
|
|
case 'd':
|
2018-01-12 09:47:42 +01:00
|
|
|
|
arg = strchr (input, ' ');
|
|
|
|
|
if (arg) {
|
|
|
|
|
addr = r_num_math (core->num, arg + 1);
|
2017-01-24 01:41:12 +01:00
|
|
|
|
}
|
|
|
|
|
break;
|
2019-05-09 17:49:27 +03:00
|
|
|
|
case '.': // "fd." list all flags at given offset
|
2018-02-25 15:01:33 +05:30
|
|
|
|
{
|
|
|
|
|
RFlagItem *flag;
|
|
|
|
|
RListIter *iter;
|
2019-05-09 17:49:27 +03:00
|
|
|
|
bool isJson = false;
|
2018-02-25 15:01:33 +05:30
|
|
|
|
const RList *flaglist;
|
2018-01-12 09:47:42 +01:00
|
|
|
|
arg = strchr (input, ' ');
|
|
|
|
|
if (arg) {
|
|
|
|
|
addr = r_num_math (core->num, arg + 1);
|
2017-04-14 10:06:06 +02:00
|
|
|
|
}
|
2018-02-25 15:01:33 +05:30
|
|
|
|
flaglist = r_flag_get_list (core->flags, addr);
|
2019-05-09 17:49:27 +03:00
|
|
|
|
isJson = strchr (input, 'j');
|
|
|
|
|
PJ *pj = pj_new ();
|
|
|
|
|
if (isJson) {
|
|
|
|
|
pj_a (pj);
|
|
|
|
|
}
|
2020-02-23 10:08:04 +02:00
|
|
|
|
|
|
|
|
|
// Sometime an address has multiple flags assigned to, show them all
|
2018-02-25 15:01:33 +05:30
|
|
|
|
r_list_foreach (flaglist, iter, flag) {
|
|
|
|
|
if (flag) {
|
2019-05-09 17:49:27 +03:00
|
|
|
|
if (isJson) {
|
2020-02-23 10:08:04 +02:00
|
|
|
|
pj_o (pj);
|
|
|
|
|
pj_ks (pj, "name", flag->name);
|
|
|
|
|
if (flag->realname) {
|
|
|
|
|
pj_ks (pj, "realname", flag->realname);
|
|
|
|
|
}
|
|
|
|
|
pj_end (pj);
|
|
|
|
|
|
2019-05-09 17:49:27 +03:00
|
|
|
|
} else {
|
2020-02-23 10:08:04 +02:00
|
|
|
|
// Print realname if exists and asm.flags.real is enabled
|
|
|
|
|
if (core->flags->realnames && flag->realname) {
|
|
|
|
|
r_cons_println (flag->realname);
|
|
|
|
|
} else {
|
|
|
|
|
r_cons_println (flag->name);
|
|
|
|
|
}
|
2019-05-09 17:49:27 +03:00
|
|
|
|
}
|
2018-02-25 15:01:33 +05:30
|
|
|
|
}
|
|
|
|
|
}
|
2019-05-09 17:49:27 +03:00
|
|
|
|
|
|
|
|
|
if (isJson) {
|
|
|
|
|
pj_end (pj);
|
|
|
|
|
r_cons_println (pj_string (pj));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (pj) {
|
|
|
|
|
pj_free (pj);
|
|
|
|
|
}
|
|
|
|
|
|
2018-02-25 15:01:33 +05:30
|
|
|
|
return 0;
|
|
|
|
|
}
|
2019-02-03 16:06:45 +01:00
|
|
|
|
case 'w': {
|
2018-01-12 09:47:42 +01:00
|
|
|
|
arg = strchr (input, ' ');
|
2019-02-03 16:06:45 +01:00
|
|
|
|
if (!arg) {
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
arg++;
|
|
|
|
|
if (!*arg) {
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
RFlag *f = core->flags;
|
|
|
|
|
RList *temp = r_flag_all_list (f, true);
|
|
|
|
|
ut64 loff = 0;
|
|
|
|
|
ut64 uoff = 0;
|
|
|
|
|
ut64 curseek = core->offset;
|
|
|
|
|
char *lmatch = NULL , *umatch = NULL;
|
|
|
|
|
RFlagItem *flag;
|
|
|
|
|
RListIter *iter;
|
|
|
|
|
r_list_sort (temp, &cmpflag);
|
|
|
|
|
r_list_foreach (temp, iter, flag) {
|
|
|
|
|
if (strstr (flag->name , arg) != NULL) {
|
|
|
|
|
if (flag->offset < core->offset) {
|
|
|
|
|
loff = flag->offset;
|
|
|
|
|
lmatch = flag->name;
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
uoff = flag->offset;
|
|
|
|
|
umatch = flag->name;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
char *match = (curseek - loff) < (uoff - curseek) ? lmatch : umatch ;
|
|
|
|
|
if (match) {
|
|
|
|
|
if (*match) {
|
|
|
|
|
r_cons_println (match);
|
|
|
|
|
}
|
2017-12-20 03:19:30 +05:30
|
|
|
|
}
|
2019-02-03 16:06:45 +01:00
|
|
|
|
r_list_free (temp);
|
2017-12-20 03:19:30 +05:30
|
|
|
|
return 0;
|
2019-02-03 16:06:45 +01:00
|
|
|
|
}
|
2012-02-27 02:40:27 +01:00
|
|
|
|
default:
|
2018-01-12 09:47:42 +01:00
|
|
|
|
arg = strchr (input, ' ');
|
|
|
|
|
if (arg) {
|
|
|
|
|
addr = r_num_math (core->num, arg + 1);
|
|
|
|
|
}
|
2012-02-27 02:40:27 +01:00
|
|
|
|
break;
|
|
|
|
|
}
|
2017-04-14 10:06:06 +02:00
|
|
|
|
f = r_flag_get_at (core->flags, addr, !strict_offset);
|
2012-02-27 02:40:27 +01:00
|
|
|
|
if (f) {
|
|
|
|
|
if (f->offset != addr) {
|
2018-01-11 22:22:32 +01:00
|
|
|
|
// if input contains 'j' print json
|
|
|
|
|
if (strchr (input, 'j')) {
|
2020-02-23 10:08:04 +02:00
|
|
|
|
PJ *pj = pj_new ();
|
|
|
|
|
pj_o (pj);
|
|
|
|
|
pj_kn (pj, "offset", f->offset);
|
|
|
|
|
pj_ks (pj, "name", f->name);
|
|
|
|
|
// Print flag's real name if defined
|
|
|
|
|
if (f->realname) {
|
|
|
|
|
pj_ks (pj, "realname", f->realname);
|
|
|
|
|
}
|
|
|
|
|
pj_end (pj);
|
|
|
|
|
r_cons_println (pj_string (pj));
|
|
|
|
|
if (pj) {
|
|
|
|
|
pj_free (pj);
|
|
|
|
|
}
|
2018-01-11 22:22:32 +01:00
|
|
|
|
} else {
|
2020-02-23 10:08:04 +02:00
|
|
|
|
// Print realname if exists and asm.flags.real is enabled
|
|
|
|
|
if (core->flags->realnames && f->realname) {
|
|
|
|
|
r_cons_printf ("%s + %d\n", f->realname,
|
|
|
|
|
(int)(addr - f->offset));
|
|
|
|
|
} else {
|
|
|
|
|
r_cons_printf ("%s + %d\n", f->name,
|
2018-01-11 22:22:32 +01:00
|
|
|
|
(int)(addr - f->offset));
|
2020-02-23 10:08:04 +02:00
|
|
|
|
}
|
2018-01-11 22:22:32 +01:00
|
|
|
|
}
|
2015-08-11 11:49:56 +02:00
|
|
|
|
} else {
|
2018-01-12 09:47:42 +01:00
|
|
|
|
if (strchr (input, 'j')) {
|
2020-02-23 10:08:04 +02:00
|
|
|
|
PJ *pj = pj_new ();
|
|
|
|
|
pj_o (pj);
|
|
|
|
|
pj_ks (pj, "name", f->name);
|
|
|
|
|
// Print flag's real name if defined
|
|
|
|
|
if (f->realname) {
|
|
|
|
|
pj_ks (pj, "realname", f->realname);
|
|
|
|
|
}
|
|
|
|
|
pj_end (pj);
|
|
|
|
|
r_cons_println (pj_string (pj));
|
|
|
|
|
pj_free (pj);
|
2018-01-11 22:22:32 +01:00
|
|
|
|
} else {
|
2020-02-23 10:08:04 +02:00
|
|
|
|
// Print realname if exists and asm.flags.real is enabled
|
|
|
|
|
if (core->flags->realnames && f->realname) {
|
|
|
|
|
r_cons_println (f->realname);
|
|
|
|
|
} else {
|
|
|
|
|
r_cons_println (f->name);
|
|
|
|
|
}
|
2018-01-11 22:22:32 +01:00
|
|
|
|
}
|
2015-08-11 11:49:56 +02:00
|
|
|
|
}
|
2012-02-27 02:40:27 +01:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case '?':
|
2018-09-17 09:50:31 +02:00
|
|
|
|
default:
|
2017-04-07 04:11:32 +02:00
|
|
|
|
if (input[1]) {
|
|
|
|
|
core->num->value = r_flag_get (core->flags, input + 1)? 1: 0;
|
|
|
|
|
} else {
|
2018-09-17 09:50:31 +02:00
|
|
|
|
r_core_cmd_help (core, help_msg_f);
|
|
|
|
|
break;
|
|
|
|
|
}
|
2015-08-11 11:49:56 +02:00
|
|
|
|
}
|
2017-11-23 14:34:07 +01:00
|
|
|
|
free (str);
|
2012-02-27 02:40:27 +01:00
|
|
|
|
return 0;
|
|
|
|
|
}
|