355 lines
9.9 KiB
C
355 lines
9.9 KiB
C
/* radare - LGPL - Copyright 2009-2013 - pancake */
|
||
|
||
static void flagbars(RCore *core) {
|
||
int total = 0;
|
||
int cols = r_cons_get_size (NULL);
|
||
RListIter *iter;
|
||
RFlagItem *flag;
|
||
r_list_foreach (core->flags->flags, iter, flag) {
|
||
total += flag->offset;
|
||
}
|
||
r_list_foreach (core->flags->flags, iter, flag) {
|
||
r_cons_printf ("%10s", flag->name);
|
||
r_print_progressbar (core->print,
|
||
(flag->offset*100)/total, cols);
|
||
r_cons_newline ();
|
||
}
|
||
}
|
||
|
||
static int cmd_flag(void *data, const char *input) {
|
||
RCore *core = (RCore *)data;
|
||
ut64 off = core->offset;
|
||
char *ptr, *str = NULL;
|
||
st64 base;
|
||
|
||
// TODO: off+=cursor
|
||
if (*input)
|
||
str = strdup (input+1);
|
||
switch (*input) {
|
||
case '=':
|
||
flagbars (core);
|
||
break;
|
||
case '2':
|
||
r_flag_get_i2 (core->flags, r_num_math (core->num, input+1));
|
||
break;
|
||
case 'R':
|
||
{
|
||
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");
|
||
}
|
||
}
|
||
break;
|
||
case 'b':
|
||
switch (input[1]) {
|
||
case ' ':
|
||
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;
|
||
}
|
||
} else core->flags->base = r_num_math (core->num, input+1);
|
||
free (str);
|
||
str = NULL;
|
||
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;
|
||
case '+':
|
||
case ' ': {
|
||
char *s = strchr (str, ' '), *s2 = NULL, *eq = strchr (str, '=');
|
||
ut32 bsze = 1; //core->blocksize;
|
||
if (eq) {
|
||
// TODO: add support for '=' char in flag comments
|
||
*eq = 0;
|
||
off = r_num_math (core->num, eq+1);
|
||
}
|
||
s = strchr (str, ' ');
|
||
if (s) {
|
||
*s = '\0';
|
||
s2 = strchr (s+1, ' ');
|
||
if (s2) {
|
||
*s2 = '\0';
|
||
if (s2[1]&&s2[2])
|
||
off = r_num_math (core->num, s2+1);
|
||
}
|
||
bsze = r_num_math (core->num, s+1);
|
||
}
|
||
if (*str == '.') {
|
||
RAnalFunction *fcn = r_anal_fcn_find (core->anal, off, 0);
|
||
if (fcn) r_anal_fcn_local_add (core->anal, fcn, off, str+1);
|
||
else eprintf ("Cannot find function at 0x%08"PFMT64x"\n", off);
|
||
} else r_flag_set (core->flags, str, off, bsze, (*input=='+'));
|
||
}
|
||
break;
|
||
case '-':
|
||
if (input[1]) {
|
||
const char *flagname = input+1;
|
||
while (*flagname==' ') flagname++;
|
||
if (*flagname=='.') {
|
||
RAnalFunction *fcn = r_anal_fcn_find (core->anal, off, 0);
|
||
if (fcn) r_anal_fcn_local_del_name (core->anal, fcn, flagname+1);
|
||
else eprintf ("Cannot find function at 0x%08"PFMT64x"\n", off);
|
||
} else {
|
||
if (strchr (flagname, '*'))
|
||
r_flag_unset_glob (core->flags, flagname);
|
||
else r_flag_unset (core->flags, flagname, NULL);
|
||
}
|
||
} else r_flag_unset_i (core->flags, off, NULL);
|
||
break;
|
||
case '.':
|
||
if (input[1]) {
|
||
if (input[1] == '*') {
|
||
if (input[2] == '*') {
|
||
r_core_anal_fcn_local_list (core, NULL, 1);
|
||
} else {
|
||
RAnalFunction *fcn = r_anal_fcn_find (core->anal, off, 0);
|
||
if (fcn) r_core_anal_fcn_local_list (core, fcn, 1);
|
||
else eprintf ("Cannot find function at 0x%08"PFMT64x"\n", off);
|
||
}
|
||
} else {
|
||
const char *name = input+((input[2]==' ')? 2:1);
|
||
RAnalFunction *fcn = r_anal_fcn_find (core->anal, off, 0);
|
||
if (fcn) {
|
||
if (*name=='-') {
|
||
r_anal_fcn_local_del_name (core->anal, fcn, name+1);
|
||
} else {
|
||
r_anal_fcn_local_add (core->anal, fcn, off, name);
|
||
}
|
||
} else eprintf ("Cannot find function at 0x%08"PFMT64x"\n", off);
|
||
}
|
||
} else {
|
||
RAnalFunction *fcn = r_anal_fcn_find (core->anal, off, 0);
|
||
if (fcn) r_core_anal_fcn_local_list (core, fcn, 0);
|
||
else eprintf ("Cannot find function at 0x%08"PFMT64x"\n", off);
|
||
}
|
||
break;
|
||
case 'l':
|
||
if (input[1] == ' ') {
|
||
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);
|
||
} else eprintf ("Missing arguments\n");
|
||
break;
|
||
#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
|
||
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);
|
||
}
|
||
} else eprintf ("Missing arguments\n");
|
||
break;
|
||
case 'S':
|
||
r_flag_sort (core->flags, (input[1]=='n'));
|
||
break;
|
||
case 's':
|
||
switch (input[1]) {
|
||
case 'r':
|
||
if (input[2]==' ')
|
||
r_flag_space_rename (core->flags, NULL, input+2);
|
||
else eprintf ("Usage: fsr [newname]\n");
|
||
break;
|
||
case 'j':
|
||
case '\0':
|
||
case '*':
|
||
r_flag_space_list (core->flags, input[1]);
|
||
break;
|
||
case ' ':
|
||
r_flag_space_set (core->flags, input+2);
|
||
break;
|
||
case 'm':
|
||
{ RFlagItem *f;
|
||
ut64 off = core->offset;
|
||
if (input[2] == ' ')
|
||
off = r_num_math (core->num, input+2);
|
||
f = r_flag_get_i (core->flags, off);
|
||
if (f) {
|
||
f->space = core->flags->space_idx;
|
||
} else eprintf ("Cannot find any flag at 0x%"PFMT64x".\n", off);
|
||
}
|
||
break;
|
||
default: {
|
||
int i, j = 0;
|
||
for (i=0; i<R_FLAG_SPACES_MAX; i++) {
|
||
if (core->flags->spaces[i])
|
||
r_cons_printf ("%02d %c %s\n", j++,
|
||
(i==core->flags->space_idx)?'*':' ',
|
||
core->flags->spaces[i]);
|
||
}
|
||
} break;
|
||
}
|
||
break;
|
||
case 'g':
|
||
r_core_cmd0 (core, "V");
|
||
break;
|
||
case 'c':
|
||
eprintf ("TODO: fc\n");
|
||
break;
|
||
case 'C':
|
||
if (input[1]==' ') {
|
||
RFlagItem *item;
|
||
char *q, *p = strdup (input+2);
|
||
q = strchr (p, ' ');
|
||
if (q) {
|
||
*q = 0;
|
||
item = r_flag_get (core->flags, p);
|
||
if (item) {
|
||
r_flag_item_set_comment (item, q+1);
|
||
} else eprintf ("Cannot find flag with name '%s'\n", p);
|
||
} else {
|
||
item = r_flag_get_i (core->flags, r_num_math (core->num, p));
|
||
if (item && item->comment) {
|
||
r_cons_printf ("%s\n", item->comment);
|
||
} else eprintf ("Cannot find item\n");
|
||
}
|
||
free (p);
|
||
} else eprintf ("Usage: fC [name] [comment]\n");
|
||
break;
|
||
case 'o':
|
||
{ // TODO: use file.fortunes // can be dangerous in sandbox mode
|
||
char *file = R2_PREFIX"/share/doc/radare2/fortunes";
|
||
char *line = r_file_slurp_random_line (file);
|
||
if (line) {
|
||
r_cons_printf (" -- %s\n", line);
|
||
free (line);
|
||
}
|
||
}
|
||
break;
|
||
case 'r':
|
||
if (input[1]==' ' && input[2]) {
|
||
char *old, *new;
|
||
RFlagItem *item;
|
||
old = str+1;
|
||
new = strchr (old, ' ');
|
||
if (new) {
|
||
*new = 0;
|
||
new++;
|
||
item = r_flag_get (core->flags, old);
|
||
} else {
|
||
new = old;
|
||
item = r_flag_get_i (core->flags, core->offset);
|
||
}
|
||
if (item) {
|
||
if (!r_flag_rename (core->flags, item, new))
|
||
eprintf ("Invalid name\n");
|
||
} else eprintf ("Cannot find flag\n");
|
||
}
|
||
break;
|
||
case '*':
|
||
case '\0':
|
||
case 'j':
|
||
r_flag_list (core->flags, *input);
|
||
break;
|
||
case 'd':
|
||
{
|
||
ut64 addr = 0;
|
||
RFlagItem *f = NULL;
|
||
switch (input[1]) {
|
||
case '?':
|
||
eprintf ("Usage: fd [offset|flag|expression]\n");
|
||
return R_FALSE;
|
||
case '\0':
|
||
addr = core->offset;
|
||
break;
|
||
default:
|
||
addr = r_num_math (core->num, input+2);
|
||
break;
|
||
}
|
||
f = r_flag_get_at (core->flags, addr);
|
||
if (f) {
|
||
if (f->offset != addr) {
|
||
r_cons_printf ("%s + %d\n", f->name, (int)(addr-f->offset));
|
||
} else r_cons_printf ("%s\n", f->name);
|
||
}
|
||
}
|
||
break;
|
||
case '?':
|
||
r_cons_printf (
|
||
"Usage: f[?] [flagname]\n"
|
||
" f ; list flags\n"
|
||
" f.[*[*]] ; list local per-function flags (*) for r2 commands (cur, all)\n"
|
||
" f* ; list flags in r commands\n"
|
||
" fj ; list flags in JSON format\n"
|
||
" fs ; display flagspaces\n"
|
||
" fs * ; set all flagspace\n"
|
||
" fs sections ; set flagspace (f will only list flags from selected ones)\n"
|
||
" fsr newname ; set flagspace (f will only list flags from selected ones)\n"
|
||
" fsm [addr] ; move flags at given address to the current flagspace\n"
|
||
" fb [addr] ; set base address for new flags\n"
|
||
" fb [addr] [flag*]; move flags matching 'flag' to relative addr\n"
|
||
" f name 12 @ 33 ; set flag 'name' with length 12 at offset 33\n"
|
||
" f name = 33 ; alias for 'f name @ 33' or 'f name 1 33'\n"
|
||
" f name 12 33 ; same as above\n"
|
||
" f name 12 33 cmt ; same as above + set flag comment\n"
|
||
" f.blah=$$+12 ; set local function label named 'blah'\n"
|
||
" f-.blah@fcn.foo ; delete local label from function at current seek (also f.-)\n"
|
||
" f+name 12 @ 33 ; like above but creates new one if doesnt exist\n"
|
||
" f-name ; remove flag 'name'\n"
|
||
" f-@addr ; remove flag at address expression\n"
|
||
" f. fname ; list all local labels for the given function\n"
|
||
" fd addr ; return flag+delta\n"
|
||
//" fc [name] [cmt] ; set execution command for a specific flag\n"
|
||
" fC [name] [cmt] ; set comment for given flag\n"
|
||
" fr [old] [[new]] ; rename flag (if no new flag current seek one is used)\n"
|
||
" fl [flagname] ; show flag length (size)\n"
|
||
" fS[on] ; sort flags by offset or name\n"
|
||
" fR [f] [t] [m] ; relocate all flags matching f&~m 'f'rom, 't'o, 'm'ask\n"
|
||
" fx[d] ; show hexdump (or disasm) of flag:flagsize\n"
|
||
" fo ; show fortunes\n");
|
||
break;
|
||
}
|
||
if (str)
|
||
free (str);
|
||
return 0;
|
||
}
|
||
|