* Initial pseudo-working implementation of r_var API
- Remove temporal code
This commit is contained in:
parent
7b96c49110
commit
0c34c746bf
7 changed files with 376 additions and 1512 deletions
70
libr/include/r_var.h
Normal file
70
libr/include/r_var.h
Normal file
|
|
@ -0,0 +1,70 @@
|
|||
#include "r_types.h"
|
||||
#include "list.h"
|
||||
|
||||
#define R_VAR_ANAL_MAX 256
|
||||
|
||||
enum {
|
||||
R_VAR_TYPE_NONE = 0,
|
||||
R_VAR_TYPE_GLOBAL,
|
||||
R_VAR_TYPE_LOCAL,
|
||||
R_VAR_TYPE_ARG,
|
||||
R_VAR_TYPE_ARGREG
|
||||
};
|
||||
|
||||
struct r_var_anal_t {
|
||||
int type;
|
||||
int delta;
|
||||
int count;
|
||||
};
|
||||
|
||||
struct r_var_type_t {
|
||||
char name[128];
|
||||
char fmt[128];
|
||||
unsigned int size;
|
||||
struct list_head list;
|
||||
};
|
||||
|
||||
struct r_var_t {
|
||||
int anal_size;
|
||||
struct r_var_anal_t anal[R_VAR_ANAL_MAX];
|
||||
struct list_head vartypes;
|
||||
struct list_head vars;
|
||||
};
|
||||
|
||||
struct r_var_access_t {
|
||||
u64 addr;
|
||||
int set;
|
||||
struct list_head list;
|
||||
};
|
||||
|
||||
struct r_var_item_t {
|
||||
int type; /* global, local... */
|
||||
u64 addr; /* address where it is used */
|
||||
u64 eaddr; /* address where it is used */
|
||||
int delta; /* */
|
||||
int arraysize; /* size of array var in bytes , 0 is no-array */
|
||||
char name[128];
|
||||
char vartype[128];
|
||||
struct list_head access; /* list of accesses for this var */
|
||||
struct list_head list;
|
||||
};
|
||||
|
||||
/* api */
|
||||
struct r_var_t *r_var_new();
|
||||
void r_var_free(struct r_var_t *var);
|
||||
int r_var_init(struct r_var_t *var);
|
||||
int r_var_type_add(struct r_var_t *var, const char *typename, int size, const char *fmt);
|
||||
int r_var_type_del(struct r_var_t *var, const char *typename);
|
||||
int r_var_type_list(struct r_var_t *var);
|
||||
const char *r_var_type_get(struct r_var_t *var, const char *datatype);
|
||||
const char *r_var_type_to_string(int type);
|
||||
|
||||
/* food */
|
||||
int r_var_item_print(struct r_var_t *var, struct r_var_item_t * v);
|
||||
int r_var_list_show(struct r_var_t *var, u64 addr);
|
||||
int r_var_list(struct r_var_t *var, u64 addr, int delta);
|
||||
|
||||
/* analyze */
|
||||
int r_var_anal_get(struct r_var_t *var, int type);
|
||||
void r_var_anal_reset(struct r_var_t *var);
|
||||
int r_var_anal_add(struct r_var_t *var, int type, int delta);
|
||||
5
libr/var/Makefile
Normal file
5
libr/var/Makefile
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
NAME=r_var
|
||||
OBJ=var.o
|
||||
DEPS=r_util r_cons
|
||||
|
||||
include ../rules.mk
|
||||
|
|
@ -1,9 +1,2 @@
|
|||
r_vars_add()
|
||||
...
|
||||
Contains old:
|
||||
vars.c
|
||||
data.c
|
||||
analyze.c - related code var analysis (after analyze a function
|
||||
return a list of accesses to local and lgobal vars)
|
||||
|
||||
See tmp/ fmi
|
||||
API for accessing and analyzing variables
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -1,143 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2008
|
||||
* pancake <youterm.com>
|
||||
*
|
||||
* radare is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* radare is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with radare; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
*/
|
||||
|
||||
#include "main.h"
|
||||
#include "code.h"
|
||||
#include "data.h"
|
||||
#include "undo.h"
|
||||
#include "flags.h"
|
||||
#include "arch/csr/dis.h"
|
||||
#include "arch/arm/disarm.h"
|
||||
#include "arch/ppc/ppc_disasm.h"
|
||||
#include "arch/m68k/m68k_disasm.h"
|
||||
#include "arch/x86/udis86/types.h"
|
||||
#include "arch/x86/udis86/extern.h"
|
||||
#include "list.h"
|
||||
|
||||
struct reflines_t *reflines = NULL;
|
||||
|
||||
static struct list_head vartypes;
|
||||
|
||||
/* variables */
|
||||
void data_comment_init(int new)
|
||||
{
|
||||
INIT_LIST_HEAD(&(vartypes));
|
||||
}
|
||||
|
||||
int data_var_type_add(const char *typename, int size, const char *fmt)
|
||||
{
|
||||
struct var_type_t *d = (struct var_type_t *)
|
||||
malloc(sizeof(struct var_type_t));
|
||||
strncpy(d->name, typename, sizeof(d->name));
|
||||
strncpy(d->fmt, fmt, sizeof(d->fmt));
|
||||
d->size = size;
|
||||
list_add(&(d->list), &vartypes);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int data_var_type_del(const char *typename)
|
||||
{
|
||||
struct list_head *pos;
|
||||
u64 ret = 0;
|
||||
|
||||
if (*typename==' ')typename=typename+1;
|
||||
|
||||
list_for_each(pos, &vartypes) {
|
||||
struct var_type_t *d = (struct var_type_t *)list_entry(pos, struct var_type_t, list);
|
||||
if (!strcmp(typename, d->name)) {
|
||||
list_del(&(d->list));
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int data_var_type_list()
|
||||
{
|
||||
struct list_head *pos;
|
||||
u64 ret = 0;
|
||||
|
||||
list_for_each(pos, &vartypes) {
|
||||
struct var_type_t *d = (struct var_type_t *)list_entry(pos, struct var_type_t, list);
|
||||
cons_printf("%s %d %s\n", d->name, d->size, d->fmt);
|
||||
}
|
||||
return ret;
|
||||
|
||||
}
|
||||
|
||||
const char *data_var_type_get(const char *datatype)
|
||||
{
|
||||
struct list_head *pos;
|
||||
u64 ret = 0;
|
||||
|
||||
list_for_each(pos, &vartypes) {
|
||||
struct var_type_t *d = (struct var_type_t *)list_entry(pos, struct var_type_t, list);
|
||||
//eprintf("---(%s)(%s)\n", d->name, datatype);
|
||||
if (!strcmp(datatype, d->name))
|
||||
return d;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int data_var_help()
|
||||
{
|
||||
cons_printf(
|
||||
"Usage: Cv [name] [size] [pm-format-string]\n"
|
||||
" Cv int 4 d ; define 'int' type\n"
|
||||
" Cv- int ; remove 'int' var type\n"
|
||||
" Cv float 4 f\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
int data_var_cmd(const char *str)
|
||||
{
|
||||
int len;
|
||||
char *vstr;
|
||||
char *arg, *arg2;
|
||||
STRALLOC(vstr, str, len);
|
||||
|
||||
if (*str==' ')str=str+1;
|
||||
switch(*str) {
|
||||
case '?':
|
||||
return data_var_help();
|
||||
case '\0':
|
||||
/* list var types */
|
||||
data_var_type_list();
|
||||
break;
|
||||
case '-':
|
||||
data_var_type_del(str+1);
|
||||
break;
|
||||
default:
|
||||
arg = strchr(str, ' ');
|
||||
if (arg==NULL)
|
||||
return data_var_help();
|
||||
*arg='\0'; arg=arg+1;
|
||||
arg2 = strchr(arg, ' ');
|
||||
if (arg2==NULL)
|
||||
return data_var_help();
|
||||
*arg2='\0'; arg2=arg2+1;
|
||||
data_var_type_add(str, atoi(arg), arg2);
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -1,311 +0,0 @@
|
|||
/* Copyleft 2009 - pancake<AT>youterm.com */
|
||||
|
||||
|
||||
#include "main.h"
|
||||
#include "list.h"
|
||||
|
||||
int var_add(u64 addr, u64 eaddr, int delta, int type, const char *vartype, const char *name, int arraysize);
|
||||
// this can be nested inside the function_t which is not defined..
|
||||
|
||||
#if 0
|
||||
struct function_t {
|
||||
char name[128];
|
||||
int framesize;
|
||||
struct list_head ranges;
|
||||
struct list_head vars;
|
||||
};
|
||||
#endif
|
||||
|
||||
static struct list_head vars;
|
||||
|
||||
/* variable types */
|
||||
enum {
|
||||
VAR_T_GLOBAL,
|
||||
VAR_T_LOCAL,
|
||||
VAR_T_ARG,
|
||||
VAR_T_ARGREG
|
||||
};
|
||||
|
||||
struct var_xs_t {
|
||||
u64 addr;
|
||||
int set;
|
||||
struct list_head list;
|
||||
};
|
||||
|
||||
struct var_t {
|
||||
int type; /* global, local... */
|
||||
u64 addr; /* address where it is used */
|
||||
u64 eaddr; /* address where it is used */
|
||||
int delta; /* */
|
||||
int arraysize; /* size of array var in bytes , 0 is no-array */
|
||||
char name[128];
|
||||
char vartype[128];
|
||||
struct list_head access; /* list of accesses for this var */
|
||||
struct list_head list;
|
||||
};
|
||||
|
||||
int var_add(u64 addr, u64 eaddr, int delta, int type, const char *vartype, const char *name, int arraysize)
|
||||
{
|
||||
struct var_t *var = (struct var_t *)malloc(sizeof(struct var_t));
|
||||
/* TODO: check of delta inside funframe */
|
||||
if (strchr(name, ' ') || strchr(vartype,' ')) {
|
||||
eprintf("Invalid name/type\n");
|
||||
return 0;
|
||||
}
|
||||
strncpy(var->name, name, sizeof(var->name));
|
||||
strncpy(var->vartype, vartype, sizeof(var->vartype));
|
||||
var->delta = delta;
|
||||
var->type = type;
|
||||
var->addr = addr;
|
||||
var->eaddr = eaddr;
|
||||
var->arraysize = arraysize;
|
||||
INIT_LIST_HEAD(&(var->access));
|
||||
list_add(&(var->list), &vars);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int var_add_access(u64 addr, int delta, int type, int set)
|
||||
{
|
||||
struct list_head *pos;
|
||||
struct var_t *v;
|
||||
int reloop = 0;
|
||||
|
||||
_reloop:
|
||||
list_for_each(pos, &vars) {
|
||||
v = (struct var_t *)list_entry(pos, struct var_t, list);
|
||||
if (addr >= v->addr) {
|
||||
//if (!strcmp(name, v->name)) {
|
||||
if (delta == v->delta && type == v->type) {
|
||||
struct var_xs_t *xs = (struct var_xs_t *)malloc(sizeof(struct var_xs_t));
|
||||
xs->addr = addr;
|
||||
xs->set = set;
|
||||
//eprintf("==> %llx\n", addr);
|
||||
/* add var access here */
|
||||
list_add(&(xs->list), &(v->access));
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
/* automatic init */
|
||||
/* detect function in CF list */
|
||||
{
|
||||
u64 from = 0LL, to = 0LL;
|
||||
if ( data_get_fun_for(addr, &from, &to) ) {
|
||||
char varname[32];
|
||||
if (delta < 0) {
|
||||
delta = -delta;
|
||||
sprintf(varname, "arg_%d", delta);
|
||||
} else sprintf(varname, "var_%d", delta);
|
||||
//eprintf("0x%08llx: NEW LOCAL VAR %d\n", from, delta);
|
||||
var_add(from, to, delta, VAR_T_LOCAL, "int32", varname, 1);
|
||||
if (reloop) {
|
||||
#warning THIS IS BUGGY: SHOULD NEVER HAPPEN
|
||||
eprintf("LOOPING AT 0x%08llx NOT ADDING AN ACCESS\n", addr);
|
||||
return 0;
|
||||
}
|
||||
reloop=1;
|
||||
goto _reloop;
|
||||
return var_add_access(addr, delta, type, set);
|
||||
} else eprintf("Cannot find bounding function at 0x%08llx\n", addr);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
const char *var_type_str(int fd)
|
||||
{
|
||||
switch(fd) {
|
||||
case VAR_T_GLOBAL: return "global";
|
||||
case VAR_T_LOCAL: return "local";
|
||||
case VAR_T_ARG: return "arg";
|
||||
case VAR_T_ARGREG: return "fastarg";
|
||||
}
|
||||
return "(?)";
|
||||
}
|
||||
|
||||
u32 var_dbg_read(int delta)
|
||||
{
|
||||
/* XXX: EBP ONLY FOR X86 */
|
||||
u32 ret;
|
||||
u64 foo = get_offset("ebp");
|
||||
foo-=delta;
|
||||
radare_read_at(foo, (u8*)&ret, 4);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
void print_mem(u64 addr, const u8 *buf, u64 len, const char *fmt, int endian);
|
||||
|
||||
int var_print_value(struct var_t *v)
|
||||
{
|
||||
struct var_type_t *t = data_var_type_get(v->vartype);
|
||||
if (t == NULL) {
|
||||
u32 value = var_dbg_read(v->delta);
|
||||
// TODO: use var type to
|
||||
cons_printf("%x", value);
|
||||
} else {
|
||||
u8 buf[1024];
|
||||
int verbose = config.verbose;
|
||||
int size = v->arraysize * t->size;
|
||||
u64 foo = get_offset("ebp");
|
||||
foo -= v->delta;
|
||||
radare_read_at(foo, buf, size);
|
||||
//eprintf("PRINT_MEM(%llx,%d,%s)\n", foo, size, t->fmt);
|
||||
config.verbose = 0;
|
||||
print_mem(foo, buf, size, t->fmt, config.endian);
|
||||
config.verbose = verbose;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* CFV */
|
||||
int var_list_show(u64 addr)
|
||||
{
|
||||
char buf[256];
|
||||
struct list_head *pos, *pos2;
|
||||
struct var_t *v;
|
||||
struct var_xs_t *x;
|
||||
|
||||
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)) {
|
||||
u32 value = var_dbg_read(v->delta);
|
||||
if (v->arraysize>1)
|
||||
cons_printf("%s %s %s[%d] = ", var_type_str(v->type), v->vartype, v->arraysize, v->name);
|
||||
else cons_printf("%s %s %s = ", var_type_str(v->type), v->vartype, v->name);
|
||||
var_print_value(v);
|
||||
/* TODO: detect pointer to strings and so on */
|
||||
if (string_flag_offset(buf, value, 0))
|
||||
cons_printf(" ; points to: %s\n", buf);
|
||||
else cons_newline();
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* 0,0 to list all */
|
||||
int var_list(u64 addr, int delta)
|
||||
{
|
||||
struct list_head *pos, *pos2;
|
||||
struct var_t *v;
|
||||
struct var_xs_t *x;
|
||||
|
||||
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)) {
|
||||
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");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int var_init()
|
||||
{
|
||||
INIT_LIST_HEAD(&vars);
|
||||
data_var_type_add("char", 1, "b");
|
||||
data_var_type_add("byte", 1, "b");
|
||||
data_var_type_add("int", 4, "d");
|
||||
data_var_type_add("int32", 4, "d");
|
||||
data_var_type_add("dword", 4, "x");
|
||||
data_var_type_add("float", 4, "f");
|
||||
}
|
||||
|
||||
int var_help()
|
||||
{
|
||||
eprintf("Try Cv?\n");
|
||||
eprintf(" Cv 12 int buffer[3]\n");
|
||||
eprintf(" Cv 12 byte buffer[1024]\n");
|
||||
}
|
||||
|
||||
int var_cmd_help()
|
||||
{
|
||||
eprintf("Try CF[aAv][gs] [delta]\n");
|
||||
eprintf(" CFag 0 = arg0 get\n");
|
||||
eprintf(" CFvs 12 = var12 set\n");
|
||||
eprintf("a = arg, A = fastarg, v = var\n");
|
||||
}
|
||||
|
||||
int var_cmd(const char *str)
|
||||
{
|
||||
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 var_list_show(config.seek);
|
||||
case 'v': // frame variable
|
||||
case 'a': // stack arg
|
||||
case 'A': // fastcall arg
|
||||
// XXX nested dup
|
||||
switch(*str) {
|
||||
case 'v': type = VAR_T_LOCAL; break;
|
||||
case 'a': type = VAR_T_ARG; break;
|
||||
case 'A': type = VAR_T_ARGREG; break;
|
||||
}
|
||||
/* Variable access CFvs = set fun var */
|
||||
switch(str[1]) {
|
||||
case '\0': return var_list(0, 0);
|
||||
case '.': return var_list(config.seek, 0);
|
||||
case 's': return var_add_access(config.seek, atoi(str+2), type, 1);
|
||||
case 'g': return var_add_access(config.seek, atoi(str+2), type, 0);
|
||||
}
|
||||
str = str+1;
|
||||
if (str[0]==' ')str=str+1;
|
||||
delta = atoi(str);
|
||||
p = strchr(str, ' ');
|
||||
if (p==NULL)
|
||||
return var_cmd_help();
|
||||
p[0]='\0'; p=p+1;
|
||||
p2 = strchr(p, ' ');
|
||||
if (p2==NULL)
|
||||
return var_help();
|
||||
p2[0]='\0'; p2=p2+1;
|
||||
p3 = strchr(p2,'[');
|
||||
if (p3 != NULL) {
|
||||
p3[0]='\0';
|
||||
p3=p3+1;
|
||||
}
|
||||
var_add(config.seek, config.seek, delta, type, p, p2, p3?atoi(p3):0);
|
||||
break;
|
||||
default:
|
||||
var_help();
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
#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
|
||||
300
libr/var/var.c
Normal file
300
libr/var/var.c
Normal file
|
|
@ -0,0 +1,300 @@
|
|||
/* radare - LGPL - Copyright 2008-2009 pancake<nopcode.org> */
|
||||
|
||||
#include "r_var.h"
|
||||
#include "r_cons.h"
|
||||
|
||||
struct r_var_t *r_var_new()
|
||||
{
|
||||
struct r_var_t *var = MALLOC_STRUCT(struct r_var_t);
|
||||
r_var_init(var);
|
||||
return var;
|
||||
}
|
||||
|
||||
void r_var_free(struct r_var_t *var)
|
||||
{
|
||||
free(var);
|
||||
}
|
||||
|
||||
int r_var_init(struct r_var_t *var)
|
||||
{
|
||||
INIT_LIST_HEAD(&(var->vartypes));
|
||||
INIT_LIST_HEAD(&(var->vars));
|
||||
|
||||
r_var_type_add(var, "char", 1, "b");
|
||||
r_var_type_add(var, "byte", 1, "b");
|
||||
r_var_type_add(var, "int", 4, "d");
|
||||
r_var_type_add(var, "int32", 4, "d");
|
||||
r_var_type_add(var, "dword", 4, "x");
|
||||
r_var_type_add(var, "float", 4, "f");
|
||||
r_var_anal_reset(var);
|
||||
|
||||
return R_TRUE;
|
||||
}
|
||||
|
||||
/* data.c */
|
||||
|
||||
int r_var_type_add(struct r_var_t *var, const char *typename, int size, const char *fmt)
|
||||
{
|
||||
struct r_var_type_t *d = (struct r_var_type_t *)
|
||||
malloc(sizeof(struct r_var_type_t));
|
||||
strncpy(d->name, typename, sizeof(d->name));
|
||||
strncpy(d->fmt, fmt, sizeof(d->fmt));
|
||||
d->size = size;
|
||||
list_add(&(d->list), &var->vartypes);
|
||||
|
||||
return R_TRUE;
|
||||
}
|
||||
|
||||
int r_var_type_del(struct r_var_t *var, const char *typename)
|
||||
{
|
||||
struct list_head *pos;
|
||||
|
||||
if (*typename==' ') typename = typename+1;
|
||||
|
||||
list_for_each(pos, &var->vartypes) {
|
||||
struct r_var_type_t *d = (struct r_var_type_t *)
|
||||
list_entry(pos, struct r_var_type_t, list);
|
||||
if (!strcmp(typename, d->name)) {
|
||||
list_del(&(d->list));
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int r_var_type_list(struct r_var_t *var)
|
||||
{
|
||||
struct list_head *pos;
|
||||
u64 ret = 0;
|
||||
|
||||
list_for_each(pos, &var->vartypes) {
|
||||
struct r_var_type_t *d = (struct r_var_type_t *)
|
||||
list_entry(pos, struct r_var_type_t, list);
|
||||
cons_printf("%s %d %s\n", d->name, d->size, d->fmt);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
struct r_var_type_d *r_var_type_get(struct r_var_t *var, const char *datatype)
|
||||
{
|
||||
struct list_head *pos;
|
||||
|
||||
list_for_each(pos, &var->vartypes) {
|
||||
struct r_var_type_t *d = (struct r_var_type_t *)
|
||||
list_entry(pos, struct r_var_type_t, list);
|
||||
//eprintf("---(%s)(%s)\n", d->name, datatype);
|
||||
if (!strcmp(datatype, d->name))
|
||||
return d;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* vars.c */
|
||||
|
||||
int r_var_add(struct r_var_t *v, u64 addr, u64 eaddr, int delta, int type, const char *vartype, const char *name, int arraysize)
|
||||
{
|
||||
struct r_var_item_t *var = MALLOC_STRUCT(struct r_var_item_t);
|
||||
/* TODO: check of delta inside funframe */
|
||||
if (strchr(name, ' ') || strchr(vartype,' ')) {
|
||||
fprintf(stderr, "r_var_add: Invalid name/type\n");
|
||||
return 0;
|
||||
}
|
||||
strncpy(var->name, name, sizeof(var->name));
|
||||
strncpy(var->vartype, vartype, sizeof(var->vartype));
|
||||
var->delta = delta;
|
||||
var->type = type;
|
||||
var->addr = addr;
|
||||
var->eaddr = eaddr;
|
||||
var->arraysize = arraysize;
|
||||
INIT_LIST_HEAD(&(var->access));
|
||||
list_add(&(var->list), &v->vars);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int r_var_add_access(struct r_var_t *var, u64 addr, int delta, int type, int set)
|
||||
{
|
||||
u64 from = 0LL, to = 0LL;
|
||||
struct list_head *pos;
|
||||
struct r_var_item_t *v;
|
||||
int reloop = 0;
|
||||
|
||||
_reloop:
|
||||
list_for_each(pos, &var->vars) {
|
||||
v = (struct r_var_item_t*)list_entry(pos, struct r_var_item_t, list);
|
||||
if (addr >= v->addr) {
|
||||
//if (!strcmp(name, v->name)) {
|
||||
if (delta == v->delta && type == v->type) {
|
||||
struct r_var_access_t *xs = MALLOC_STRUCT(struct r_var_access_t);
|
||||
xs->addr = addr;
|
||||
xs->set = set;
|
||||
/* add var access here */
|
||||
list_add(&(xs->list), &(v->access));
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
/* automatic init */
|
||||
/* detect function in CF list */
|
||||
from = to = 0LL;
|
||||
// XXX THIS IS FOR R_META?
|
||||
if ( data_get_fun_for(addr, &from, &to) ) {
|
||||
char varname[32];
|
||||
if (delta < 0) {
|
||||
delta = -delta;
|
||||
sprintf(varname, "arg_%d", delta);
|
||||
} else sprintf(varname, "var_%d", delta);
|
||||
//eprintf("0x%08llx: NEW LOCAL VAR %d\n", from, delta);
|
||||
r_var_add(var, from, to, delta, R_VAR_TYPE_LOCAL, "int32", varname, 1);
|
||||
if (reloop) {
|
||||
#warning THIS IS BUGGY: SHOULD NEVER HAPPEN
|
||||
fprintf(stderr, "LOOPING AT 0x%08llx NOT ADDING AN ACCESS\n", addr);
|
||||
return 0;
|
||||
}
|
||||
reloop=1;
|
||||
goto _reloop;
|
||||
return r_var_add_access(var, addr, delta, type, set);
|
||||
} else fprintf(stderr, "Cannot find bounding function at 0x%08llx\n", addr);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* XXX: this is a static method..no need for $self argument */
|
||||
const char *r_var_type_to_string(int type)
|
||||
{
|
||||
switch(type) {
|
||||
case R_VAR_TYPE_GLOBAL: return "global";
|
||||
case R_VAR_TYPE_LOCAL: return "local";
|
||||
case R_VAR_TYPE_ARG: return "arg";
|
||||
case R_VAR_TYPE_ARGREG: return "fastarg";
|
||||
}
|
||||
return "(?)";
|
||||
}
|
||||
|
||||
#if 0
|
||||
/* This stuff belongs to the plugins realm */
|
||||
u32 var_dbg_read(int delta)
|
||||
{
|
||||
/* XXX: EBP ONLY FOR X86 */
|
||||
u32 ret;
|
||||
u64 foo = get_offset("ebp");
|
||||
foo-=delta;
|
||||
radare_read_at(foo, (u8*)&ret, 4);
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
int r_var_item_print(struct r_var_t *var, struct r_var_item_t * v)
|
||||
{
|
||||
struct r_var_type_t *t = r_var_type_get(var, v->vartype);
|
||||
if (t == NULL) {
|
||||
u32 value = var_dbg_read(v->delta);
|
||||
// TODO: use var type to
|
||||
r_cons_printf("%x", value);
|
||||
} else {
|
||||
#if 0
|
||||
u8 buf[1024];
|
||||
int size = v->arraysize * t->size;
|
||||
u64 foo = get_offset("ebp");
|
||||
foo -= v->delta;
|
||||
//XXX radare_read_at(foo, buf, size);
|
||||
//eprintf("PRINT_MEM(%llx,%d,%s)\n", foo, size, t->fmt);
|
||||
//XXX print_mem(foo, buf, size, t->fmt, config.endian);
|
||||
#endif
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* CFV */
|
||||
int r_var_list_show(struct r_var_t *var, u64 addr)
|
||||
{
|
||||
char buf[256];
|
||||
struct list_head *pos;
|
||||
struct r_var_item_t *v;
|
||||
|
||||
list_for_each(pos, &var->vars) {
|
||||
v = (struct r_var_item_t*)list_entry(pos, struct r_var_item_t, list);
|
||||
if (addr == 0 || (addr >= v->addr && addr <= v->eaddr)) {
|
||||
u32 value = var_dbg_read(v->delta);
|
||||
if (v->arraysize>1) {
|
||||
r_cons_printf("%s %s %s[%d] = ",
|
||||
r_var_type_to_string(v->type),
|
||||
v->vartype, v->arraysize, v->name);
|
||||
} else {
|
||||
r_cons_printf("%s %s %s = ",
|
||||
r_var_type_to_string(v->type), v->vartype, v->name);
|
||||
}
|
||||
r_var_item_print(var, v);
|
||||
/* TODO: detect pointer to strings and so on */
|
||||
#if 0
|
||||
if (string_flag_offset(buf, value, 0))
|
||||
r_cons_printf(" ; points to: %s\n", buf);
|
||||
else
|
||||
#endif
|
||||
r_cons_newline();
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* 0,0 to list all */
|
||||
int r_var_list(struct r_var_t *var, u64 addr, int delta)
|
||||
{
|
||||
struct list_head *pos, *pos2;
|
||||
struct r_var_item_t*v;
|
||||
struct r_var_access_t *x;
|
||||
|
||||
list_for_each(pos, &var->vars) {
|
||||
v = (struct r_var_item_t*)list_entry(pos, struct r_var_item_t, list);
|
||||
if (addr == 0 || (addr >= v->addr && addr <= v->eaddr)) {
|
||||
cons_printf("0x%08llx - 0x%08llx type=%s type=%s name=%s delta=%d array=%d\n",
|
||||
v->addr, v->eaddr, r_var_type_to_string(v->type),
|
||||
v->vartype, v->name, v->delta, v->arraysize);
|
||||
list_for_each_prev(pos2, &v->access) {
|
||||
x = (struct r_var_access_t *)list_entry(pos2, struct r_var_access_t, list);
|
||||
r_cons_printf(" 0x%08llx %s\n", x->addr, x->set?"set":"get");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* analize.c */
|
||||
|
||||
// XXX move to code.h
|
||||
void r_var_anal_reset(struct r_var_t *var)
|
||||
{
|
||||
memset(&var->anal, '\0', sizeof(var->anal));
|
||||
var->anal_size = 0;
|
||||
}
|
||||
|
||||
int r_var_anal_add(struct r_var_t *var, int type, int delta)
|
||||
{
|
||||
int i, hole = -1;
|
||||
for(i=0;i<R_VAR_ANAL_MAX;i++) {
|
||||
if (var->anal[i].type == type && var->anal[i].delta == delta) {
|
||||
var->anal[i].count++;
|
||||
return 0;
|
||||
} else
|
||||
if (var->anal[i].type==R_VAR_TYPE_NONE && hole==-1) {
|
||||
hole = i;
|
||||
}
|
||||
}
|
||||
if (hole==-1) {
|
||||
fprintf(stderr, "analyze.c: No space left in var pool\n");
|
||||
return -1;
|
||||
}
|
||||
var->anal[hole].type = type;
|
||||
var->anal[hole].delta = delta;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int r_var_anal_get(struct r_var_t *var, int type)
|
||||
{
|
||||
int i, ctr = 0;
|
||||
for(i=0;i<R_VAR_ANAL_MAX;i++) {
|
||||
if (var->anal[i].type == type)
|
||||
ctr++;
|
||||
}
|
||||
return ctr;
|
||||
}
|
||||
Loading…
Reference in a new issue