rizin/libr/var/var.c
Nibble 94445e1540 * Change the name of some types
- s/u64/ut64/
  - s/u32/ut32/
  - s/u16/ut16/
  - s/u8/ut8/
2009-07-08 13:49:55 +02:00

301 lines
7.4 KiB
C

/* radare - LGPL - Copyright 2008-2009 pancake<nopcode.org> */
#include "r_var.h"
#include "r_cons.h"
R_API struct r_var_t *r_var_new()
{
struct r_var_t *var = MALLOC_STRUCT(struct r_var_t);
r_var_init(var);
return var;
}
R_API void r_var_free(struct r_var_t *var)
{
free(var);
}
R_API 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 */
R_API 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;
}
R_API 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;
}
R_API int r_var_type_list(struct r_var_t *var)
{
struct list_head *pos;
ut64 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);
printf("%s %d %s\n", d->name, d->size, d->fmt);
}
return ret;
}
R_API struct r_var_type_t *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 */
R_API int r_var_add(struct r_var_t *v, ut64 addr, ut64 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;
}
R_API int r_var_add_access(struct r_var_t *var, ut64 addr, int delta, int type, int set)
{
ut64 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 USE RMETA HERE!!
#if 0
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);
#endif
return 0;
}
/* XXX: this is a static method..no need for $self argument */
R_API 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 */
ut32 var_dbg_read(int delta)
{
/* XXX: EBP ONLY FOR X86 */
ut32 ret;
ut64 foo = get_offset("ebp");
foo-=delta;
radare_read_at(foo, (ut8*)&ret, 4);
return ret;
}
#endif
R_API 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) {
ut32 value = 0; //XXX var_dbg_read(v->delta);
// TODO: use var type to
r_cons_printf("%x", value);
} else {
#if 0
ut8 buf[1024];
int size = v->arraysize * t->size;
ut64 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 */
R_API int r_var_list_show(struct r_var_t *var, ut64 addr)
{
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)) {
//ut32 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 */
R_API int r_var_list(struct r_var_t *var, ut64 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)) {
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);
printf(" 0x%08llx %s\n", x->addr, x->set?"set":"get");
}
}
}
return 0;
}
/* analize.c */
// XXX move to code.h
R_API void r_var_anal_reset(struct r_var_t *var)
{
memset(&var->anal, '\0', sizeof(var->anal));
var->anal_size = 0;
}
R_API 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;
}
R_API 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;
}