* Oops. fix ruby plugin build
* Added dummy r_trace r_meta and r_var - With readme, dummy code and comments..
This commit is contained in:
parent
49b637328f
commit
7b96c49110
10 changed files with 1924 additions and 2 deletions
|
|
@ -57,6 +57,8 @@
|
|||
-----------
|
||||
- Define a way to iterate flags from vala
|
||||
- We probably need more methods
|
||||
- support to define relations between flags
|
||||
(flag hirearchies)
|
||||
|
||||
|| hash ||
|
||||
----------
|
||||
|
|
|
|||
26
libr/debug/README
Normal file
26
libr/debug/README
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
r_debug
|
||||
=======
|
||||
|
||||
Debugger API for radare2
|
||||
|
||||
|
||||
We need to connect multiple pieces...
|
||||
|
||||
debugger engine: vm, qemu, bochs, ptrace, mach, w32dbg...
|
||||
|
||||
controlflow commands: (should be splitted in two layers)
|
||||
|
||||
- continue -- low level
|
||||
- step -- low level
|
||||
- trace --- high level one
|
||||
- ...
|
||||
|
||||
the control flow commands depend on other stuff to decide
|
||||
how to work..this is for example if the arch doesnt supports
|
||||
continuation, we should provide a step based continue. The
|
||||
same when a watchpoint is activated and the arch didnt
|
||||
supports hardware regs for this purpose.
|
||||
|
||||
We also need a load/store/dump/restore functions to move the
|
||||
program from one engine to another (ptrace -> qemu).. we should
|
||||
provide a way for all this operations between them.
|
||||
|
|
@ -6,7 +6,7 @@ all: lua.so dummy.so ruby.so python.so
|
|||
|
||||
python.so:
|
||||
-${CC} ${CFLAGS} -I/usr/include/python2.5 \
|
||||
-fPIC -shared -o python.so python.c -lpython
|
||||
-fPIC -shared -o python.so python.c -lpython >/dev/null 2>&1
|
||||
|
||||
lua.so: lua.o
|
||||
-${CC} ${CFLAGS} -fPIC -shared -o lua.so lua.c -Wl,-R..
|
||||
|
|
|
|||
|
|
@ -52,7 +52,7 @@ static int init(void *user)
|
|||
ruby_init();
|
||||
ruby_init_loadpath();
|
||||
|
||||
rb_eval_string_protect("require 'irb'", &err);
|
||||
rb_eval_string_protect("require 'irb'", NULL);
|
||||
core = user;
|
||||
rb_RadareCmd = rb_define_class("RadareInternal", rb_cObject);
|
||||
rb_define_method(rb_RadareCmd, "cmd", radare_ruby_cmd, 1);
|
||||
|
|
|
|||
47
libr/meta/README
Normal file
47
libr/meta/README
Normal file
|
|
@ -0,0 +1,47 @@
|
|||
r_meta
|
||||
======
|
||||
|
||||
enum {
|
||||
R_META_DATA,
|
||||
R_META_CODE,
|
||||
R_META_CODE_XREF,
|
||||
R_META_DATA_XREF,
|
||||
R_META_STRING,
|
||||
R_META_FUNCTION,
|
||||
R_META_STRUCT,
|
||||
R_META_COMMENT,
|
||||
R_META_FOLDER
|
||||
}
|
||||
|
||||
struct r_meta_item_t {
|
||||
int type;
|
||||
u64 addr;
|
||||
u64 size;
|
||||
char *data;
|
||||
struct list_head list;
|
||||
};
|
||||
|
||||
struct r_meta_t {
|
||||
struct list_head comments;
|
||||
struct list_head xrefs;
|
||||
};
|
||||
|
||||
struct r_meta_t * meta = r_meta_new();
|
||||
|
||||
/* get list of xrefs to this addr */
|
||||
r_meta_xrefs_get(meta, 0x8040400);
|
||||
r_meta_xrefs_add(meta, 0x8040400, 0x8049030);
|
||||
|
||||
r_meta_list(meta, RMetaCallback)
|
||||
|
||||
r_meta_add(meta, R_META_CODE_XREF, 100, 200);
|
||||
r_meta_add_s(meta, R_META_COMMENT, 100, "Hello world");
|
||||
r_meta_add_s(meta, R_META_STRUCT, 100, "xxi");
|
||||
|
||||
r_meta_get(meta, R_META_COMMENT, 0x804800);
|
||||
r_meta_get_range(meta, R_META_COMMENT, 0x804800, 0x8049000);
|
||||
|
||||
// TODO: rethink argument order
|
||||
r_meta_get_closer(meta, 0x0394, R_META_STRING, R_META_GET_FORWARD);
|
||||
|
||||
|
||||
334
libr/trace/trace.c
Normal file
334
libr/trace/trace.c
Normal file
|
|
@ -0,0 +1,334 @@
|
|||
/*
|
||||
* Copyright (C) 2008
|
||||
* pancake <youterm.com>
|
||||
*
|
||||
* radare is part of the radare project
|
||||
*
|
||||
* 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 "utils.h"
|
||||
#include "print.h"
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
struct list_head traces;
|
||||
static unsigned int n_traces = 0;
|
||||
static int trace_changed = 0;
|
||||
static int trace_tag = -1;
|
||||
|
||||
int trace_tag_get()
|
||||
{
|
||||
return trace_tag;
|
||||
}
|
||||
|
||||
int trace_tag_set(int id)
|
||||
{
|
||||
if (id>=-1&&id<64) {
|
||||
trace_tag = id;
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int trace_sort()
|
||||
{
|
||||
struct list_head *pos, *pos2;
|
||||
struct list_head *n, *n2;
|
||||
int ch=0;
|
||||
|
||||
if (trace_changed==0)
|
||||
return 0;
|
||||
|
||||
list_for_each_safe(pos, n, &traces) {
|
||||
struct trace_t *r = list_entry(pos, struct trace_t, list);
|
||||
list_for_each_safe(pos2, n2, &traces) {
|
||||
struct trace_t *r2 = list_entry(pos2, struct trace_t, list);
|
||||
if ((r != r2) && (r->addr > r2->addr)) {
|
||||
list_move(pos, pos2);
|
||||
ch=1;
|
||||
}
|
||||
}
|
||||
}
|
||||
return trace_changed = ch;
|
||||
}
|
||||
|
||||
struct trace_t *trace_get(u64 addr, int tag)
|
||||
{
|
||||
struct list_head *pos;
|
||||
list_for_each(pos, &traces) {
|
||||
struct trace_t *h= list_entry(pos, struct trace_t, list);
|
||||
if (tag != -1 && !(h->tags & (1<<tag)))
|
||||
continue;
|
||||
if (h->addr == addr)
|
||||
return h;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// num of traces for an address
|
||||
int trace_times(u64 addr)
|
||||
{
|
||||
struct trace_t *t = trace_get(addr, trace_tag);
|
||||
return t?t->times:0;
|
||||
}
|
||||
|
||||
int trace_count(u64 addr)
|
||||
{
|
||||
struct trace_t *t = trace_get(addr, trace_tag);
|
||||
return t?t->count:0;
|
||||
}
|
||||
|
||||
int trace_index(u64 addr)
|
||||
{
|
||||
int idx = -1;
|
||||
struct list_head *pos;
|
||||
list_for_each(pos, &traces) {
|
||||
struct trace_t *h = list_entry(pos, struct trace_t, list);
|
||||
idx++;
|
||||
if (h->addr == addr)
|
||||
return idx;
|
||||
}
|
||||
return idx;
|
||||
}
|
||||
|
||||
int trace_set_times(u64 addr, int times)
|
||||
{
|
||||
char bytes[16];
|
||||
struct trace_t *t;
|
||||
struct list_head *pos;
|
||||
|
||||
if (arch_aop == NULL)
|
||||
return -1;
|
||||
/* update times counter */
|
||||
list_for_each(pos, &traces) {
|
||||
t = list_entry(pos, struct trace_t, list);
|
||||
if (t->addr == addr) {
|
||||
t->times = times;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int trace_add(u64 addr)
|
||||
{
|
||||
char bytes[16];
|
||||
struct trace_t *t;
|
||||
struct list_head *pos;
|
||||
|
||||
if (arch_aop == NULL)
|
||||
return -1;
|
||||
|
||||
if (config_get("trace.dup")) {
|
||||
/* update times counter */
|
||||
list_for_each(pos, &traces) {
|
||||
t = list_entry(pos, struct trace_t, list);
|
||||
if (t->addr == addr) {
|
||||
if (trace_tag != -1)
|
||||
t->tags |= trace_tag;
|
||||
++(t->times);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
list_for_each(pos, &traces) {
|
||||
t = list_entry(pos, struct trace_t, list);
|
||||
if (t->addr == addr) {
|
||||
t->count = ++n_traces;
|
||||
gettimeofday(&(t->tm), NULL);
|
||||
if (trace_tag != -1)
|
||||
t->tags |= trace_tag;
|
||||
return ++(t->times);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
t = (struct trace_t *)malloc(sizeof(struct trace_t));
|
||||
memset(t,'\0',sizeof(struct trace_t));
|
||||
t->addr = addr;
|
||||
t->times = 1;
|
||||
radare_read_at(addr, bytes, 16);
|
||||
t->opsize = arch_aop(addr, bytes, NULL);
|
||||
gettimeofday(&(t->tm), NULL);
|
||||
t->count = ++n_traces;
|
||||
if (trace_tag != -1)
|
||||
t->tags |= trace_tag;
|
||||
trace_changed = 1;
|
||||
list_add_tail(&(t->list), &traces);
|
||||
|
||||
//eprintf("new trace (0x%08x)\n", (unsigned long)addr);
|
||||
return t->times;
|
||||
}
|
||||
|
||||
u64 trace_range(u64 from, int tag)
|
||||
{
|
||||
struct trace_t *h;
|
||||
u64 last = from;
|
||||
u64 last2 = 0LL;
|
||||
|
||||
while(last != last2) {
|
||||
last2 = last;
|
||||
h = trace_get(last, tag);
|
||||
if (h) {
|
||||
if (tag != -1 && !(h->tags & (1<<tag)))
|
||||
continue;
|
||||
last = last + h->opsize;
|
||||
}
|
||||
}
|
||||
|
||||
return last;
|
||||
}
|
||||
|
||||
#if 1
|
||||
u64 trace_next(u64 from, int tag)
|
||||
{
|
||||
u64 next = 0xFFFFFFFFFFFFFFFFLL;
|
||||
struct list_head *pos;
|
||||
struct trace_t *h;
|
||||
|
||||
list_for_each(pos, &traces) {
|
||||
h = list_entry(pos, struct trace_t, list);
|
||||
if (tag != -1 && !(h->tags & (1<<tag)))
|
||||
continue;
|
||||
if (h->addr > from && h->addr < next)
|
||||
next = h->addr;
|
||||
}
|
||||
|
||||
if (next == 0xFFFFFFFFFFFFFFFFLL)
|
||||
return 0LL;
|
||||
return next;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
/* buggy version */
|
||||
u64 trace_next(u64 from)
|
||||
{
|
||||
u64 next;
|
||||
int next_init = 0;
|
||||
struct list_head *pos;
|
||||
struct trace_t *h;
|
||||
|
||||
list_for_each(pos, &traces) {
|
||||
h = list_entry(pos, struct trace_t, list);
|
||||
if (!next_init) {
|
||||
if (h->addr > from && h->addr < next) {
|
||||
next = h->addr;
|
||||
next_init = 1;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if (h->addr > from && h->addr < next)
|
||||
next = h->addr;
|
||||
}
|
||||
|
||||
if (next_init == 0)
|
||||
return NULL;
|
||||
|
||||
return next;
|
||||
}
|
||||
#endif
|
||||
|
||||
void trace_show(int plain, int tag)
|
||||
{
|
||||
u64 from = 0LL;
|
||||
u64 last;
|
||||
char bytes[32];
|
||||
char opcode[64];
|
||||
struct list_head *pos;
|
||||
struct trace_t *h;
|
||||
|
||||
if (tag != -1)
|
||||
eprintf("Displaying tag: %d\n", tag+1);
|
||||
|
||||
trace_sort();
|
||||
opcode[0]='\0';
|
||||
/* get the lower address */
|
||||
list_for_each(pos, &traces) {
|
||||
h = list_entry(pos, struct trace_t, list);
|
||||
if (from == 0LL)
|
||||
from = h->addr;
|
||||
if (h->addr < from)
|
||||
from = h->addr;
|
||||
if (tag != -1 && !(h->tags & (1<<tag)))
|
||||
continue;
|
||||
switch(plain) {
|
||||
case 1:
|
||||
cons_printf("0x%08llx %d %d tags=%08llx\n",
|
||||
h->addr, h->times, h->count, h->tags);
|
||||
break;
|
||||
case 2:
|
||||
config.verbose=0;
|
||||
cons_printf("%03d %03d ", h->times, h->count);
|
||||
sprintf(opcode, "pd 1 @ 0x%08llx", h->addr);
|
||||
radare_cmd_raw(opcode, 0);
|
||||
//radare_read_at(h->addr, bytes, 32);
|
||||
//udis_arch_string(config.arch, opcode, bytes, config.endian, h->addr, 32, 0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (plain>0)
|
||||
return;
|
||||
|
||||
while(from) {
|
||||
last = trace_range(from, tag);
|
||||
if (last == from)
|
||||
break;
|
||||
// TODO: show timestamps
|
||||
if (plain==0)
|
||||
cons_printf("0x%08llx - 0x%08llx\n", from, last);
|
||||
else cons_printf("ar+ 0x%08llx 0x%08llx\n", from, last);
|
||||
from = trace_next(last, tag);
|
||||
cons_flush();
|
||||
}
|
||||
}
|
||||
|
||||
void trace_init()
|
||||
{
|
||||
INIT_LIST_HEAD(&traces);
|
||||
}
|
||||
|
||||
void trace_reset()
|
||||
{
|
||||
struct list_head *pos;
|
||||
struct trace_t *h;
|
||||
list_for_each(pos, &traces) {
|
||||
h = list_entry(pos, struct trace_t, list);
|
||||
free(h);
|
||||
}
|
||||
INIT_LIST_HEAD(&traces);
|
||||
}
|
||||
|
||||
int trace_get_between(u64 from, u64 to)
|
||||
{
|
||||
int ctr = 0;
|
||||
struct list_head *pos;
|
||||
struct trace_t *h;
|
||||
|
||||
/* get the lower address */
|
||||
list_for_each(pos, &traces) {
|
||||
h = list_entry(pos, struct trace_t, list);
|
||||
if (trace_tag != -1 && !(h->tags & (1<<trace_tag)))
|
||||
continue;
|
||||
if (h->addr >= from && h->addr <=to)
|
||||
ctr++;
|
||||
}
|
||||
|
||||
return ctr;
|
||||
}
|
||||
9
libr/var/README
Normal file
9
libr/var/README
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
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
|
||||
1050
libr/var/tmp/analyze.c
Normal file
1050
libr/var/tmp/analyze.c
Normal file
File diff suppressed because it is too large
Load diff
143
libr/var/tmp/data.c
Normal file
143
libr/var/tmp/data.c
Normal file
|
|
@ -0,0 +1,143 @@
|
|||
/*
|
||||
* 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;
|
||||
}
|
||||
311
libr/var/tmp/vars.c
Normal file
311
libr/var/tmp/vars.c
Normal file
|
|
@ -0,0 +1,311 @@
|
|||
/* 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
|
||||
Loading…
Reference in a new issue