mirror of
https://github.com/radareorg/radare2.git
synced 2025-02-26 09:06:02 +00:00
* Import more r_anal_var stuff from r1
- Implemented 'af[aAv]' command. - In r1 this command is 'CF[aAv]' - Variable contents are not displayed yet
This commit is contained in:
parent
675b04e7cd
commit
3c8ddce624
11
TODO
11
TODO
@ -69,18 +69,9 @@ TODO pancake
|
||||
| r_asm > r_vm |
|
||||
| r_debug > r_reg |
|
||||
`-----------------'
|
||||
* Implement visual function editor .. its done hacky in anal.c
|
||||
* Implement remote:// socket:// and listen://
|
||||
{
|
||||
* we need an api to define local vars and accesses in function
|
||||
- arg/var set name/get value/ ..
|
||||
- afv{gs}
|
||||
- CFv{gs}.. => afv
|
||||
CFv. ; show variables for current function
|
||||
CFv 20 int ; define local var
|
||||
CFv 20 int loopvar ; define local var named 'loopvar' of type 'int'
|
||||
CFvg 20 @ 0x8048000 ; access 'get' to delta 20 var (creates var if not exist)
|
||||
CFvs 20 @ 0x8049000 ; access 'set' to delta 20 var ("")
|
||||
CFV @ 0x8049000 ; Show local variables and arg values at function
|
||||
* Implement RAnalCall (analyze function arguments, return values, propagate types..)
|
||||
- define number of arguments for given function
|
||||
- warn if signature and analysis differs in number of args or so..
|
||||
|
@ -4,6 +4,7 @@
|
||||
|
||||
#include <r_anal.h>
|
||||
#include <r_util.h>
|
||||
#include <r_cons.h>
|
||||
#include <r_list.h>
|
||||
|
||||
R_API RAnalVar *r_anal_var_new() {
|
||||
@ -146,7 +147,7 @@ R_API RAnalVar *r_anal_var_get(RAnal *anal, RAnalFcn *fcn, int delta, int type)
|
||||
RAnalVar *vari;
|
||||
RListIter *iter;
|
||||
r_list_foreach (fcn->vars, iter, vari)
|
||||
if (vari->type == type && vari->delta == delta)
|
||||
if ((type==-1||vari->type == type) && vari->delta == delta)
|
||||
return vari;
|
||||
return NULL;
|
||||
}
|
||||
@ -195,3 +196,61 @@ R_API RAnalVarAccess *r_anal_var_access_get(RAnal *anal, RAnalVar *var, ut64 fro
|
||||
return acci;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
// XXX: move into core_anal?
|
||||
R_API int r_anal_var_list_show(RAnal *anal, RAnalFcn *fcn, ut64 addr) {
|
||||
RAnalVar *v;
|
||||
RListIter *iter;
|
||||
|
||||
if (!fcn || !fcn->vars) {
|
||||
eprintf ("No function here\n");
|
||||
return R_FALSE;
|
||||
}
|
||||
r_list_foreach (fcn->vars, iter, v) {
|
||||
if (addr == 0 || (addr >= v->addr && addr <= v->eaddr)) {
|
||||
//ut32 value = r_var_dbg_read(v->delta);
|
||||
if (v->array>1)
|
||||
r_cons_printf("%s %s %s[%d] = ",
|
||||
r_anal_var_type_to_str(anal, v->type), v->vartype,
|
||||
v->array, v->name);
|
||||
else r_cons_printf("%s %s %s = ", r_anal_var_type_to_str (anal, v->type),
|
||||
v->vartype, v->name);
|
||||
// TODO: implement r_var_dbg_read using r_vm or r_num maybe?? sounds dupped
|
||||
// XXX: not fully implemented
|
||||
r_cons_printf ("0x%"PFMT64x, 0LL);
|
||||
//r_var_print_value(anal, v);
|
||||
/* TODO: detect pointer to strings and so on */
|
||||
//if (string_flag_offset(NULL, buf, value, 0))
|
||||
// r_cons_printf(" ; %s\n", buf);
|
||||
//else
|
||||
r_cons_newline();
|
||||
}
|
||||
}
|
||||
|
||||
return R_TRUE;
|
||||
}
|
||||
|
||||
/* 0,0 to list all */
|
||||
R_API int r_anal_var_list(RAnal *anal, RAnalFcn *fcn, ut64 addr, int delta) {
|
||||
RAnalVarAccess *x;
|
||||
RAnalVar *v;
|
||||
RListIter *iter, *iter2;
|
||||
|
||||
if (!fcn || !fcn->vars) {
|
||||
eprintf ("No function here\n");
|
||||
return R_FALSE;
|
||||
}
|
||||
r_list_foreach (fcn->vars, iter, v) {
|
||||
if (addr == 0 || (addr >= v->addr && addr <= v->eaddr)) {
|
||||
r_cons_printf("0x%08llx - 0x%08llx type=%s type=%s name=%s delta=%d array=%d\n",
|
||||
v->addr, v->eaddr, r_anal_var_type_to_str(anal, v->type),
|
||||
v->vartype, v->name, v->delta, v->array);
|
||||
r_list_foreach (v->accesses, iter2, x) {
|
||||
r_cons_printf(" 0x%08llx %s\n", x->addr, x->set?"set":"get");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
285
libr/core/cmd.c
285
libr/core/cmd.c
@ -1559,6 +1559,285 @@ static void cmd_syscall_do(RCore *core, int num) {
|
||||
r_cons_printf (")\n");
|
||||
}
|
||||
|
||||
|
||||
#if 1
|
||||
/* TODO: Move into cmd_anal() */
|
||||
static void var_help() {
|
||||
eprintf("Try afv?\n");
|
||||
eprintf(" afv 12 int buffer[3]\n");
|
||||
eprintf(" afv 12 byte buffer[1024]\n");
|
||||
eprintf("Try af[aAv][gs] [delta] [[addr]]\n");
|
||||
eprintf(" afag 0 = arg0 get\n");
|
||||
eprintf(" afvs 12 = var12 set\n");
|
||||
eprintf("a = arg, A = fastarg, v = var\n");
|
||||
eprintf("TODO: [[addr]] is not yet implemented. use @\n");
|
||||
}
|
||||
|
||||
static int var_cmd(RCore *core, const char *str) {
|
||||
RAnalFcn *fcn = r_anal_fcn_find (core->anal, core->offset);
|
||||
char *p,*p2,*p3;
|
||||
int type, delta, len = strlen(str)+1;
|
||||
|
||||
p = alloca(len);
|
||||
memcpy(p, str, len);
|
||||
str = p;
|
||||
|
||||
switch(*str) {
|
||||
case 'V': // show vars in human readable format
|
||||
return r_anal_var_list_show(core->anal, fcn, core->offset);
|
||||
case '?':
|
||||
var_help();
|
||||
return 0;
|
||||
case 'v': // frame variable
|
||||
case 'a': // stack arg
|
||||
case 'A': // fastcall arg
|
||||
// XXX nested dup
|
||||
switch (*str) {
|
||||
case 'v': type = R_ANAL_VAR_TYPE_LOCAL; break;
|
||||
case 'a': type = R_ANAL_VAR_TYPE_ARG; break;
|
||||
case 'A': type = R_ANAL_VAR_TYPE_ARGREG; break;
|
||||
default:
|
||||
eprintf ("Unknown type\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Variable access CFvs = set fun var */
|
||||
switch(str[1]) {
|
||||
case '\0': return r_anal_var_list (core->anal, fcn, 0, 0);
|
||||
case '?': var_help(); return 0;
|
||||
case '.': return r_anal_var_list (core->anal, fcn, core->offset, 0);
|
||||
case 's':
|
||||
case 'g':
|
||||
if (str[2]!='\0') {
|
||||
RAnalVar *var = r_anal_var_get (core->anal, fcn, atoi (str+2), R_ANAL_VAR_TYPE_LOCAL);
|
||||
return r_anal_var_access_add (core->anal, var, atoi (str+2), (str[1]=='g')?0:1);
|
||||
}
|
||||
break;
|
||||
}
|
||||
str++;
|
||||
if (str[0]==' ') str++;
|
||||
delta = atoi (str);
|
||||
p = strchr (str, ' ');
|
||||
if (p==NULL) {
|
||||
var_help();
|
||||
return 0;
|
||||
}
|
||||
p[0]='\0'; p++;
|
||||
p2 = strchr (p, ' ');
|
||||
if (p2) {
|
||||
p2[0]='\0'; p2 = p2+1;
|
||||
p3 = strchr (p2,'[');
|
||||
if (p3 != NULL) {
|
||||
p3[0]='\0';
|
||||
p3=p3+1;
|
||||
}
|
||||
r_anal_var_add (core->anal, fcn, core->offset, delta, type, p, p2, p3?atoi(p3):0);
|
||||
} else var_help();
|
||||
break;
|
||||
default:
|
||||
var_help();
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
-- function boundaries are used to limit variables life-cycle --
|
||||
// global vars are handled as flags??
|
||||
// "CV 0x8049200 x global_counter
|
||||
// local vars
|
||||
// types: glar: g=global, l=local, a=arg, r=argreg
|
||||
Cv l d i @ 0x8048200
|
||||
/* using code analysis we can identify local var accesses */
|
||||
|
||||
f.ex:
|
||||
; Set var0
|
||||
0x4a13c014, mov [ebp-0x34], eax
|
||||
|
||||
; set name for variable accessed.
|
||||
Cvn counter @ 0x4a13c014
|
||||
|
||||
stack frame {
|
||||
var1 { offset, size, type, name }
|
||||
var2 { offset, size, type, name }
|
||||
}
|
||||
|
||||
// how to track a variable
|
||||
|
||||
#endif
|
||||
|
||||
////// VISUAL /////////
|
||||
|
||||
#if 0
|
||||
void var_index_show(ut64 addr, int idx)
|
||||
{
|
||||
int i = 0;
|
||||
struct list_head *pos, *pos2;
|
||||
struct var_t *v;
|
||||
struct var_xs_t *x;
|
||||
int window = 15;
|
||||
int wdelta = (idx>5)?idx-5:0;
|
||||
|
||||
list_for_each(pos, &vars) {
|
||||
v = (struct var_t *)list_entry(pos, struct var_t, list);
|
||||
if (addr == 0 || (addr >= v->addr && addr <= v->eaddr)) {
|
||||
if (i>=wdelta) {
|
||||
if (i> window+wdelta) {
|
||||
cons_printf("...\n");
|
||||
break;
|
||||
}
|
||||
if (idx == i) printf(" * ");
|
||||
else printf(" ");
|
||||
cons_printf("0x%08llx - 0x%08llx type=%s type=%s name=%s delta=%d array=%d\n",
|
||||
v->addr, v->eaddr, var_type_str(v->type),
|
||||
v->vartype, v->name, v->delta, v->arraysize);
|
||||
list_for_each_prev(pos2, &v->access) {
|
||||
x = (struct var_xs_t *)list_entry(pos2, struct var_xs_t, list);
|
||||
cons_printf(" 0x%08llx %s\n", x->addr, x->set?"set":"get");
|
||||
}
|
||||
}
|
||||
i++;
|
||||
}
|
||||
//}
|
||||
}
|
||||
}
|
||||
|
||||
/* Like emenu but for real */
|
||||
void var_visual_menu()
|
||||
{
|
||||
struct list_head *pos;
|
||||
const char *ptr;
|
||||
char *fs = NULL;
|
||||
char *fs2 = NULL;
|
||||
int option = 0;
|
||||
int _option = 0;
|
||||
int delta = 9;
|
||||
int menu = 0;
|
||||
int i,j, ch;
|
||||
int hit;
|
||||
int level = 0;
|
||||
int show;
|
||||
char old[1024];
|
||||
char cmd[1024];
|
||||
ut64 size, addr = config.seek;
|
||||
old[0]='\0';
|
||||
|
||||
while(1) {
|
||||
cons_gotoxy(0,0);
|
||||
cons_clear();
|
||||
cons_printf("Visual code analysis manipulation\n");
|
||||
switch(level) {
|
||||
case 0:
|
||||
cons_printf("-[ functions ]------------------- \n");
|
||||
cons_printf("(a) add (x)xrefs (q)quit\n");
|
||||
cons_printf("(m) modify (c)calls (g)go\n");
|
||||
cons_printf("(d) delete (v)variables\n");
|
||||
addr = var_functions_show(option);
|
||||
break;
|
||||
case 1:
|
||||
cons_printf("-[ variables ]------------------- 0x%08llx\n", addr);
|
||||
cons_printf("(a) add (x)xrefs (q)quit\n");
|
||||
cons_printf("(m) modify (c)calls (g)go\n");
|
||||
cons_printf("(d) delete (v)variables\n");
|
||||
var_index_show(addr, option);
|
||||
break;
|
||||
case 2:
|
||||
cons_printf("-[ calls ]----------------------- 0x%08llx\n", addr);
|
||||
sprintf(old, "aCf@0x%08llx", addr);
|
||||
cons_flush();
|
||||
radare_cmd(old, 0);
|
||||
//cons_printf("\n");
|
||||
break;
|
||||
case 3:
|
||||
cons_printf("-[ xrefs ]----------------------- 0x%08llx\n", addr);
|
||||
sprintf(old, "Cx~0x%08llx", addr);
|
||||
radare_cmd(old, 0);
|
||||
//cons_printf("\n");
|
||||
break;
|
||||
}
|
||||
cons_flushit();
|
||||
// show indexable vars
|
||||
ch = cons_readchar();
|
||||
ch = cons_get_arrow(ch); // get ESC+char, return 'hjkl' char
|
||||
switch(ch) {
|
||||
case 'a':
|
||||
switch(level) {
|
||||
case 0:
|
||||
cons_set_raw(0);
|
||||
printf("Address: ");
|
||||
fflush(stdout);
|
||||
if (!fgets(old, sizeof(old), stdin)) break;
|
||||
old[strlen(old)-1] = 0;
|
||||
if (!old[0]) break;
|
||||
addr = get_math(old);
|
||||
printf("Size: ");
|
||||
fflush(stdout);
|
||||
if (!fgets(old, sizeof(old), stdin)) break;
|
||||
old[strlen(old)-1] = 0;
|
||||
if (!old[0]) break;
|
||||
size = get_math(old);
|
||||
printf("Name: ");
|
||||
fflush(stdout);
|
||||
if (!fgets(old, sizeof(old), stdin)) break;
|
||||
old[strlen(old)-1] = 0;
|
||||
flag_set(old, addr, 0);
|
||||
sprintf(cmd, "CF %lld @ 0x%08llx", size, addr);
|
||||
radare_cmd(cmd, 0);
|
||||
cons_set_raw(1);
|
||||
break;
|
||||
case 1:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 'd':
|
||||
switch(level) {
|
||||
case 0:
|
||||
data_del(addr, DATA_FUN, 0);
|
||||
// XXX correcly remove all the data contained inside the size of the function
|
||||
flag_remove_at(addr);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 'x':
|
||||
level = 3;
|
||||
break;
|
||||
case 'c':
|
||||
level = 2;
|
||||
break;
|
||||
case 'v':
|
||||
level = 1;
|
||||
break;
|
||||
case 'j':
|
||||
option++;
|
||||
break;
|
||||
case 'k':
|
||||
if (--option<0)
|
||||
option = 0;
|
||||
break;
|
||||
case 'g': // go!
|
||||
radare_seek(addr, SEEK_SET);
|
||||
return;
|
||||
case ' ':
|
||||
case 'l':
|
||||
level = 1;
|
||||
_option = option;
|
||||
break;
|
||||
case 'h':
|
||||
case 'b': // back
|
||||
level = 0;
|
||||
option = _option;
|
||||
break;
|
||||
case 'q':
|
||||
if (level==0)
|
||||
return;
|
||||
level = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
static int cmd_anal(void *data, const char *input) {
|
||||
const char *ptr;
|
||||
RCore *core = (RCore *)data;
|
||||
@ -1731,6 +2010,11 @@ static int cmd_anal(void *data, const char *input) {
|
||||
} else eprintf("No function defined at 0x%08"PFMT64x"\n", addr);
|
||||
}
|
||||
break;
|
||||
case 'a':
|
||||
case 'A':
|
||||
case 'v':
|
||||
var_cmd (core, input+1);
|
||||
break;
|
||||
case '?':
|
||||
r_cons_printf (
|
||||
"Usage: af[?+-l*]\n"
|
||||
@ -1739,6 +2023,7 @@ static int cmd_anal(void *data, const char *input) {
|
||||
" af- [addr] ; Clean all function analysis data (or function at addr)\n"
|
||||
" afl [fcn name] ; List functions\n"
|
||||
" afs [addr] [fcnsign] ; Get/set function signature at current address\n"
|
||||
" af[aAv][?] [arg] ; Manipulate args, fastargs and variables in function\n"
|
||||
" af* ; Output radare commands\n");
|
||||
break;
|
||||
default:
|
||||
|
@ -224,6 +224,8 @@ enum {
|
||||
|
||||
typedef struct r_anal_var_t {
|
||||
char *name; /* name of the variable */
|
||||
ut64 addr; // not used correctly?
|
||||
ut64 eaddr; // not used correctly?
|
||||
int delta; /* delta offset inside stack frame */
|
||||
int dir; /* direction (in, out) */
|
||||
int type; /* global, local... */
|
||||
@ -364,6 +366,10 @@ R_API char* r_anal_reflines_str(struct r_anal_t *anal, struct r_anal_refline_t *
|
||||
ut64 addr, int opts);
|
||||
R_API int r_anal_reflines_middle(RAnal *anal, RAnalRefline *list, ut64 addr, int len);
|
||||
|
||||
/* TO MOVE into r_core */
|
||||
R_API int r_anal_var_list_show(RAnal *anal, RAnalFcn *fcn, ut64 addr);
|
||||
R_API int r_anal_var_list(RAnal *anal, RAnalFcn *fcn, ut64 addr, int delta);
|
||||
|
||||
/* plugin pointers */
|
||||
extern RAnalPlugin r_anal_plugin_csr;
|
||||
extern RAnalPlugin r_anal_plugin_arm;
|
||||
|
Loading…
x
Reference in New Issue
Block a user