diff --git a/libr/Makefile b/libr/Makefile index e71e7d1f2f..ae429e09ae 100644 --- a/libr/Makefile +++ b/libr/Makefile @@ -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 diff --git a/libr/cons/cons.c b/libr/cons/cons.c index f8d30e5ed7..5aa7150049 100644 --- a/libr/cons/cons.c +++ b/libr/cons/cons.c @@ -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; diff --git a/libr/core/cmd.c b/libr/core/cmd.c index 0bf0062e61..18057106ef 100644 --- a/libr/core/cmd.c +++ b/libr/core/cmd.c @@ -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"); diff --git a/libr/core/config.c b/libr/core/config.c index 2a2be480e7..778eca46eb 100644 --- a/libr/core/config.c +++ b/libr/core/config.c @@ -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; diff --git a/libr/debug/README b/libr/debug/README index e16689e71a..57cd1cef44 100644 --- a/libr/debug/README +++ b/libr/debug/README @@ -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) diff --git a/libr/debug/debug.c b/libr/debug/debug.c index 4f098d418d..579fc34d4f 100644 --- a/libr/debug/debug.c +++ b/libr/debug/debug.c @@ -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;ireg.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) diff --git a/libr/debug/p/ptrace.c b/libr/debug/p/ptrace.c index e8b22654f5..d871cd1552 100644 --- a/libr/debug/p/ptrace.c +++ b/libr/debug/p/ptrace.c @@ -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) diff --git a/libr/include/r_cons.h b/libr/include/r_cons.h index 27e9f0a9fc..baa135e4d6 100644 --- a/libr/include/r_cons.h +++ b/libr/include/r_cons.h @@ -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); diff --git a/libr/include/r_debug.h b/libr/include/r_debug.h index 3359ea1f65..bd3fdceae6 100644 --- a/libr/include/r_debug.h +++ b/libr/include/r_debug.h @@ -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); diff --git a/libr/include/r_io.h b/libr/include/r_io.h index f8978b57a8..32778f1d79 100644 --- a/libr/include/r_io.h +++ b/libr/include/r_io.h @@ -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); diff --git a/libr/include/r_reg.h b/libr/include/r_reg.h index d49a5a010a..8f7d456d30 100644 --- a/libr/include/r_reg.h +++ b/libr/include/r_reg.h @@ -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 diff --git a/libr/io/undo.c b/libr/io/undo.c index bc3630bcda..a6831aea11 100644 --- a/libr/io/undo.c +++ b/libr/io/undo.c @@ -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() { diff --git a/libr/reg/reg.c b/libr/reg/reg.c index e2373c954f..1701d8f85e 100644 --- a/libr/reg/reg.c +++ b/libr/reg/reg.c @@ -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; } diff --git a/libr/search/regexp.c b/libr/search/regexp.c index 7621cf7fec..944cf7e9f9 100644 --- a/libr/search/regexp.c +++ b/libr/search/regexp.c @@ -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; diff --git a/libr/search/search.c b/libr/search/search.c index ab4cb2659b..e8031edbaf 100644 --- a/libr/search/search.c +++ b/libr/search/search.c @@ -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; } diff --git a/libr/util/hex.c b/libr/util/hex.c index 65e32de55b..9fd9d3e162 100644 --- a/libr/util/hex.c +++ b/libr/util/hex.c @@ -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; diff --git a/libr/util/str.c b/libr/util/str.c index 40db819075..ab5028850d 100644 --- a/libr/util/str.c +++ b/libr/util/str.c @@ -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; diff --git a/libr/vm/vm.c b/libr/vm/vm.c index 6ec90a3c58..871b4799ac 100644 --- a/libr/vm/vm.c +++ b/libr/vm/vm.c @@ -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: