mirror of
https://github.com/radareorg/radare2.git
synced 2025-01-19 12:22:43 +00:00
* 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:
parent
1fd5c3118e
commit
4fcf226269
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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");
|
||||
|
@ -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;
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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()
|
||||
{
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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:
|
||||
|
Loading…
x
Reference in New Issue
Block a user