* Lot of random work on multiple fronts

* Add 'var' in build liblist and 'vapi/t' for make clean
* Add ^C handler for r_cons. support for callbacks
* Add support for ./m ELF for example to interpret the output of commands
* Fix a bug in the regexp algorithm that can get into infinite loop
* Binmask can now contain non hexpair values
* Add '/m' search regexp matches using the new R_SEARCH_REGEXP algorithm
  - Handle ^C in search loop..needs to use callback method
* Properly cleanup the flag names
* Added asm.bits and asm.os eval vars
* Added some random tips for debug in README
  - Stupid snippets for import/export data between modules
  - Register support requires a rethink
* Initial work on the integration of r_io_undo() api
This commit is contained in:
pancake 2009-02-17 00:09:40 +01:00
parent 1fd5c3118e
commit 4fcf226269
18 changed files with 207 additions and 23 deletions

View File

@ -2,7 +2,7 @@
PREFIX=../prefix
# Libraries
LIBLIST=io util lib meta lang flags bin macro hash line cons line print config syscall range socket cmd asm anal search diff debug reg core
LIBLIST=io util lib meta lang flags bin macro hash line cons line print config syscall range socket cmd asm anal search diff debug reg core var
# Under development
@ -48,3 +48,4 @@ todo:
clean:
for lib in ${LIBLIST}; do ( cd $${lib} && ${MAKE} clean ); done
cd vapi/t && ${MAKE} clean

View File

@ -41,6 +41,39 @@ int r_cons_noflush = 0;
static int grepline = -1, greptoken = -1, grepcounter = 0, grepneg = 0;
static char *grepstr = NULL;
int r_cons_breaked = 0;
static void (*r_cons_break_cb)(void *user);
static void *r_cons_break_user;
static void break_signal(int sig)
{
r_cons_breaked = 1;
printf("break received\n");
if (r_cons_break_cb)
r_cons_break_cb(r_cons_break_user);
}
void r_cons_break(void (*cb)(void *u), void *user)
{
r_cons_breaked = 0;
r_cons_break_user = user;
r_cons_break_cb = cb;
printf("break enabled\n");
#if __UNIX__
signal(SIGINT, break_signal);
#endif
}
void r_cons_break_end()
{
printf("break end\n");
r_cons_breaked = 0;
#if __UNIX__
signal(SIGINT, SIG_IGN);
#endif
}
int r_cons_init()
{
r_cons_stdin_fd = stdin;

View File

@ -67,7 +67,22 @@ static int cmd_interpret(void *data, const char *input)
"Usage: . [file] | [!command] | [(macro)]\n"
" . foo.rs ; interpret r script\n"
" .!rabin -ri $FILE ; interpret output of command\n"
" .(foo 1 2 3) ; run macro 'foo' with args 1, 2, 3\n");
" .(foo 1 2 3) ; run macro 'foo' with args 1, 2, 3\n"
" ./m ELF ; interpret output of command /m ELF as r. commands\n");
break;
default:
{
char *str = r_core_cmd_str(core, input);
char *ptr = str;
while(1) {
char *eol = strchr(ptr, '\n');
if (eol) eol[0]='\0';
r_core_cmd(core, ptr, 0);
if (!eol) break;
ptr = eol+1;
}
free(str);
}
break;
}
return 0;
@ -285,22 +300,20 @@ static int cmd_flag(void *data, const char *input)
char *str = alloca(len);
//u64 seek = core->seek;
//u64 size = core->blocksize;
memcpy(str, input, len);
memcpy(str, input+1, len);
ptr = strchr(str+1, ' ');
if (ptr) {
*ptr='\0';
ptr = strchr(ptr+1, ' ');
if (ptr) {
*ptr='\0';
}
if (ptr) *ptr='\0';
// TODO redefine seek and size here
}
switch(input[0]) {
case '+':
r_flag_set(&core->flags, input+1, core->seek, core->blocksize, 1);
r_flag_set(&core->flags, str, core->seek, core->blocksize, 1);
break;
case ' ':
r_flag_set(&core->flags, input+1, core->seek, core->blocksize, 0);
r_flag_set(&core->flags, str, core->seek, core->blocksize, 0);
break;
case '-':
r_flag_unset(&core->flags, input+1);
@ -579,6 +592,24 @@ static int cmd_search(void *data, const char *input)
r_search_begin(core->search);
dosearch = 1;
break;
case 'm': /* match regexp */
{
char *inp = strdup(input+2);
char *res = r_str_lchr(inp+1, inp[0]);
char *opt = NULL;
if (res > inp) {
opt = strdup(res+1);
res[1]='\0';
}
r_search_free(core->search);
core->search = r_search_new(R_SEARCH_REGEXP);
r_search_kw_add(core->search, inp, opt);
r_search_begin(core->search);
dosearch = 1;
free(inp);
free(opt);
}
break;
case 'x': /* search hex */
r_search_free(core->search);
core->search = r_search_new(R_SEARCH_KEYWORD);
@ -587,12 +618,16 @@ static int cmd_search(void *data, const char *input)
dosearch = 1;
break;
default:
r_cons_printf("Usage: /[x/] [arg]\n"
r_cons_printf("Usage: /[xm/] [arg]\n"
" / foo ; search for string 'foo'\n"
" /m /E.F/i ; match regular expression\n"
" /x ff0033 ; search for hex string\n"
" // ; repeat last search\n");
break;
}
if (core->search->n_kws==0) {
printf("No keywords defined\n");
} else
if (dosearch) {
/* set callback */
/* TODO: handle last block of data */
@ -600,13 +635,20 @@ static int cmd_search(void *data, const char *input)
/* TODO: launch search in background support */
buf = (u8 *)malloc(core->blocksize);
r_search_set_callback(core->search, &__cb_hit, &core);
r_cons_break(NULL, NULL);
for(at = core->seek; at < core->file->size; at += core->blocksize) {
if (r_cons_breaked)
break;
r_io_lseek(&core->io, core->file->fd, at, R_IO_SEEK_SET);
ret = r_io_read(&core->io, core->file->fd, buf, core->blocksize);
if (ret != core->blocksize)
break;
r_search_update(core->search, &at, buf, ret);
if (r_search_update(core->search, &at, buf, ret) == -1) {
printf("search:update error\n");
break;
}
}
r_cons_break_end();
}
return R_TRUE;
}
@ -868,7 +910,12 @@ static int r_core_cmd_subst(struct r_core_t *core, char *cmd, int *rs, int *rfd,
}
ptr = strchr(cmd, '@');
if (ptr) {
char *pt = ptr;
ptr[0]='\0';
while(pt[0]==' '||pt=='\t') {
pt[0]='\0';
pt = pt-1;
}
*rs = 1;
if (ptr[1]=='@') {
fprintf(stderr, "TODO: foreach @ loop\n");

View File

@ -9,7 +9,9 @@ int r_core_config_init(struct r_core_t *core)
//r_config_callback_int("");
r_config_set(cfg, "asm.arch", "x86");
r_config_set_i(cfg, "asm.bits", 32);
r_config_set(cfg, "asm.syntax", "x86");
r_config_set(cfg, "asm.os", "linux");
#if 0
node = config_set("asm.profile", "default");
// node->callback = &config_asm_profile;

View File

@ -24,3 +24,15 @@ controlflow commands: (should be splitted in two layers)
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.
[continue]
|--- check if bp api allows us to continue or we should step into..
|--- check if debug plugin supports continue
[getregs]
|--- r_reg give us a list of registers
| - dr (show bitsize debug registers) // 32 by default
| - dr 32 (show 32 bit debug registers) // depends on size
| - dr eax (show 'eax' register value)
| - dr al (show 8bit register 'al')
| - dr eax=33 (set 'eax' register value)

View File

@ -149,6 +149,18 @@ int r_debug_register_set(struct r_debug_t *dbg, int reg, u64 value)
return R_TRUE;
}
/* for debugging purposes? */
int r_debug_register_list(struct r_debug_t *dbg)
{
int i =0;
for(i=0;i<dbg->reg.nregs;i++) {
u64 value;
r_debug_register_get(dbg, i, &value);
printf("%d %s 0x%08llx\n", i, dbg->reg.regs[i], value);
}
return R_TRUE;
}
/* mmu */
int r_debug_mmu_alloc(struct r_debug_t *dbg, u64 size, u64 *addr)

View File

@ -31,11 +31,19 @@ int r_debug_ptrace_continue(int pid)
return ptrace(PTRACE_CONT, pid, addr, data);
}
int r_debug_ptrace_import(struct r_debug_handle_t *from)
{
//int pid = from->export(R_DEBUG_GET_PID);
//int maps = from->export(R_DEBUG_GET_MAPS);
}
struct r_debug_handle_t {
.step = &r_debug_ptrace_step,
.cont = &r_debug_ptrace_continue,
.attach = &r_debug_ptrace_attach,
.detach = &r_debug_ptrace_detach,
// .import = &r_debug_ptrace_import,
// .export = &r_debug_ptrace_export,
};
#if 0
int r_debug_ptrace_init(struct r_debug_t *dbg)

View File

@ -18,7 +18,10 @@ extern FILE *stdin_fd;
extern FILE *r_cons_stdin_fd;
extern int r_cons_stdout_fd;
extern int r_cons_stdout_file;
extern int r_cons_breaked;
void r_cons_break(void (*cb)(void *u), void *user);
void r_cons_break_end();
/* pipe */
int r_cons_pipe_open(const char *file, int append);
void r_cons_pipe_close(int fd);

View File

@ -24,7 +24,7 @@ struct r_debug_t {
int tid; /* selected thread id */
int swstep; /* steps with software traps */
int steps; /* counter of steps done */
struct r_reg_t reg; /* counter of steps done */
struct r_reg_t reg;
/* io */
int (*read)(int pid, u64 addr, u8 *buf, int len);
int (*write)(int pid, u64 addr, u8 *buf, int len);

View File

@ -14,7 +14,7 @@
#define R_IO_SEEK_CUR 1
#define R_IO_SEEK_END 2
#define IO_MAP_N 10
#define IO_MAP_N 32
struct r_io_maps_t {
int fd;
char file[128];
@ -23,6 +23,18 @@ struct r_io_maps_t {
struct list_head list;
};
/* stores write and seek changes */
#define R_IO_UNDOS 64
struct r_io_undo_t {
struct list_head undo_w_list;
int w_init;
int w_lock;
u64 seek[R_IO_UNDOS];
int fd[R_IO_UNDOS];
int idx;
int lim;
};
struct r_io_t {
int fd;
u64 seek;
@ -38,12 +50,17 @@ struct r_io_t {
struct list_head maps;
};
//struct r_io_handle_fd_t {
// ... store io changes here
//};
struct r_io_handle_t {
void *handle;
char *name;
char *desc;
void *widget;
int (*init)();
struct r_io_undo_t undo;
struct debug_t *debug;
int (*system)(struct r_io_t *io, int fd, const char *);
int (*open)(struct r_io_t *io, const char *, int rw, int mode);

View File

@ -22,4 +22,6 @@ struct r_reg_t {
char **regs;
};
int r_reg_set_arch(struct r_reg_t *reg, int arch, int bits);
#endif

View File

@ -1,5 +1,5 @@
/*
* Copyright (C) 2007, 2008
* Copyright (C) 2007, 2008, 2009
* pancake <@youterm.com>
*
* radare is free software; you can redistribute it and/or modify
@ -23,6 +23,12 @@
#include "list.h"
#include "undo.h"
#if 0
* Handle changes in write and seeks
* Per-fd history log
#endif
#if 0
/* History for writes support indexing and undo/redo with state flags */
static struct list_head undo_w_list;
static int undo_w_init = 0;
@ -33,6 +39,21 @@ static int undo_w_lock = 0;
static u64 undos[UNDOS];
static int undos_idx = 0;
static int undos_lim = 0;
#endif
int r_io_undo_init(struct r_io_undo_t *undo)
{
u->undo_w_init = 0;
u->undo_w_lock = 0;
u->undos_idx = 0;
u->undos_lim = 0;
return R_TRUE;
}
// u64 r_io_undo_get_last()
{
}
u64 undo_get_last_seek()
{

View File

@ -40,8 +40,10 @@ struct r_reg_arch_t x86 {
}
#endif
int r_reg_set(struct r_reg_t *reg, int arch, int bits)
int r_reg_set_arch(struct r_reg_t *reg, int arch, int bits)
{
int ret = R_TRUE;
switch(arch) {
case R_ASM_ARCH_X86:
switch(bits) {
@ -59,6 +61,12 @@ int r_reg_set(struct r_reg_t *reg, int arch, int bits)
break;
}
break;
/* TODO: add more architectures */
case R_ASM_ARCH_ARM:
case R_ASM_ARCH_MIPS:
default:
ret = R_FALSE;
break;
}
return R_TRUE;
return ret;
}

View File

@ -16,16 +16,23 @@ int r_search_regexp_update(struct r_search_t *s, u64 from, const u8 *buf, int le
list_for_each_prev(pos, &s->kws) {
struct r_search_kw_t *kw = list_entry(pos, struct r_search_kw_t, list);
int reflags = REG_EXTENDED;
int delta = 0;
int ret, delta = 0;
regmatch_t matches[10];
regex_t compiled;
if (strchr(kw->binmask, 'i'))
reflags |= REG_ICASE;
regcomp(&compiled, kw->keyword, reflags);
if (regcomp(&compiled, kw->keyword, reflags)) {
fprintf(stderr, "Cannot compile '%s' regexp\n",kw->keyword);
return -1;
}
foo:
while (!regexec(&compiled, buffer+delta, 1, &matches, 0)) {
ret = regexec(&compiled, buffer+delta, 1, &matches, 0);
if (ret) {
return 0;
} else
do {
if (s->callback)
s->callback(kw, s->user, (u64)from+matches[0].rm_so+delta);
else printf("hit%d_%d 0x%08llx ; %s\n",
@ -34,7 +41,9 @@ int r_search_regexp_update(struct r_search_t *s, u64 from, const u8 *buf, int le
delta += matches[0].rm_so+1;
kw->count++;
count++;
}
} while(!regexec(&compiled, buffer+delta, 1, &matches, 0));
if (delta == 0)
return 0;
/* TODO: check if skip 0 works */
skipz = strchr(buffer, '\0');
@ -42,7 +51,8 @@ int r_search_regexp_update(struct r_search_t *s, u64 from, const u8 *buf, int le
if (skipz && skipz+1 < end) {
for(;!*skipz&&end;skipz=skipz+1);
delta = skipz-buffer;
goto foo;
if (kw->count>0)
goto foo;
}
}
return count;

View File

@ -172,12 +172,17 @@ int r_search_kw_add(struct r_search_t *s, const char *kw, const char *bm)
struct r_search_kw_t *k = MALLOC_STRUCT(struct r_search_kw_t);
if (k == NULL)
return R_FALSE;
if (bm == NULL) bm = "";
strncpy(k->keyword, kw, sizeof(k->keyword));
strncpy(k->bin_keyword, kw, sizeof(k->keyword));
k->keyword_length = strlen(kw);
strncpy(k->binmask, bm, sizeof(k->binmask));
k->binmask_length = r_hex_str2bin(bm, k->bin_binmask);
if (k->binmask_length == -1)
k->binmask_length = strlen(bm);
printf("kw add\n");
list_add(&(k->list), &(s->kws));
s->n_kws++;
return R_TRUE;
}
@ -192,6 +197,7 @@ int r_search_kw_add_hex(struct r_search_t *s, const char *kw, const char *bm)
strncpy(k->binmask, bm, sizeof(k->binmask));
k->binmask_length = r_hex_str2bin(bm, k->bin_binmask);
list_add(&(k->list), &(s->kws));
s->n_kws++;
return R_TRUE;
}
@ -208,6 +214,7 @@ int r_search_kw_add_bin(struct r_search_t *s, const u8 *kw, int kw_len, const u8
r_hex_bin2str(kw, kw_len, k->keyword);
r_hex_bin2str(bm, bm_len, k->binmask);
list_add(&(k->list), &(s->kws));
s->n_kws++;
return R_TRUE;
}

View File

@ -96,8 +96,8 @@ int r_hex_str2bin(const char *in, u8 *out) // 0A 3B 4E A0
continue;
}
if (r_hex_to_byte(&c, ptr[0])) {
eprintf("binstr: Invalid hexa string at %d ('0x%02x') (%s).\n", (int)(ptr-in), ptr[0], in);
return 0;
//eprintf("binstr: Invalid hexa string at %d ('0x%02x') (%s).\n", (int)(ptr-in), ptr[0], in);
return -1;
}
c |= d;
if (j++ == 0) c <<= 4;

View File

@ -105,7 +105,7 @@ char *r_str_ichr(char *str, char chr)
char *r_str_lchr(char *str, char chr)
{
int len = strlen(str);
int len = strlen(str)+1;
for(;len>=0;len--)
if (str[len]==chr)
return str+len;

View File

@ -196,6 +196,7 @@ int r_vm_init(struct r_vm_t *vm, int init)
//vm_mmu_real(vm, config_get_i("vm.realio"));
/* vm_dbg_arch_x86_nregs */
/* XXX: this is hardcoded ..should be moved outside or as in plugins */
switch (1) { //config.arch) {
#if 0
case ARCH_X86_64: