From 8081f02601087c01eee016ec19bf8765ccadcd6f Mon Sep 17 00:00:00 2001 From: pancake Date: Fri, 1 Oct 2010 11:10:59 +0200 Subject: [PATCH] * Fix uninitialized variable in rabin2 * Fix null pointer handling in rbin when no xtr plugin found * Initial draft code for the x86 debug registers implementation * Fix avr* command --- TODO | 8 +- binr/rabin2/rabin2.c | 19 ++-- libr/bin/bin.c | 4 +- libr/bin/format/mach0/dyldcache.c | 7 +- libr/bin/p/bin_xtr_dyldcache.c | 2 +- libr/core/cmd.c | 4 +- libr/debug/p/drx.c | 167 ++++++++++++++++++++++++++++++ libr/vm/reg.c | 25 ++--- libr/vm/vm.c | 3 +- swig/python/test-r_cons.py | 1 - 10 files changed, 206 insertions(+), 34 deletions(-) create mode 100644 libr/debug/p/drx.c diff --git a/TODO b/TODO index acd034a9f6..0bb436c7e1 100644 --- a/TODO +++ b/TODO @@ -59,9 +59,8 @@ TODO edu TODO pancake ------------ -* Import r_vm register values from flags or from r_debug->r_reg - - r_vm must use mmu cache when emulating code - - use the one from r_io? and deprecate vm->mmu_cache? +* Embed RBin inside RCoreFile +* Implement DRX support * Record trace of register status for each function when running - r_reg_arena_copy(); { @@ -93,6 +92,9 @@ Bindings Refactoring =========== +* Import r_vm register values from flags or from r_debug->r_reg + - r_vm must use mmu cache when emulating code + - use the one from r_io? and deprecate vm->mmu_cache? * Review the r_flags api * add pipe_to_buffer..not only file descriptors * r_config set_int and so..simplify diff --git a/binr/rabin2/rabin2.c b/binr/rabin2/rabin2.c index ebee252075..be15c8eb42 100644 --- a/binr/rabin2/rabin2.c +++ b/binr/rabin2/rabin2.c @@ -120,7 +120,7 @@ static int rabin_show_main() { static int rabin_extract(int all) { char out[512], *ptr; - int i; + int i = 0; if (all) { for (i=0; inarch; i++) { @@ -138,12 +138,16 @@ static int rabin_extract(int all) { if ((ptr = strrchr (bin->arch[i].file, '/'))) ptr = ptr+1; else ptr = bin->arch[i].file; - snprintf (out, sizeof (out), "%s.%s_%i", ptr, - bin->arch[i].info->arch, bin->arch[i].info->bits); - if (!r_file_dump (out, bin->curarch->buf->buf, bin->curarch->size)) { - eprintf ("Error extracting %s\n", out); - return R_FALSE; - } else eprintf ("%s created\n", out); + if (bin->arch[i].info == NULL) { + eprintf ("No extract info found.\n"); + } else { + snprintf (out, sizeof (out), "%s.%s_%i", ptr, + bin->arch[i].info->arch, bin->arch[i].info->bits); + if (!r_file_dump (out, bin->curarch->buf->buf, bin->curarch->size)) { + eprintf ("Error extracting %s\n", out); + return R_FALSE; + } else eprintf ("%s created\n", out); + } } return R_TRUE; } @@ -447,6 +451,7 @@ static void rabin_list_archs() { int i; for (i=0; inarch; i++) { + if (bin->arch[i].info) printf ("%s_%i %s (%s)\n", bin->arch[i].info->arch, bin->arch[i].info->bits, bin->arch[i].file, bin->arch[i].info->machine); diff --git a/libr/bin/bin.c b/libr/bin/bin.c index a187f05965..62dee6ac6f 100644 --- a/libr/bin/bin.c +++ b/libr/bin/bin.c @@ -137,13 +137,13 @@ static int r_bin_extract(RBin *bin, const char* file) { bin->file = r_file_abspath (file); list_for_each (pos, &bin->binxtrs) { RBinXtrPlugin *h = list_entry (pos, RBinXtrPlugin, list); - if (h->check && h->check (bin)) { + if (h->check && h->check (bin)) bin->curxtr = h; - } } if (bin->curxtr && bin->curxtr->extract) n = bin->curxtr->extract (bin); else { + // TODO XXX: fill bin->arch[0].info! bin->arch[0].file = strdup (bin->file); if (!(buf = (ut8*)r_file_slurp (bin->file, &bin->arch[0].size))) return 0; diff --git a/libr/bin/format/mach0/dyldcache.c b/libr/bin/format/mach0/dyldcache.c index 7fc4ff1fca..cc69ed996b 100644 --- a/libr/bin/format/mach0/dyldcache.c +++ b/libr/bin/format/mach0/dyldcache.c @@ -6,9 +6,7 @@ #include "dyldcache.h" static int r_bin_dyldcache_init(struct r_bin_dyldcache_obj_t* bin) { - int len; - - len = r_buf_fread_at(bin->b, 0, (ut8*)&bin->hdr, "16c4il", 1); + int len = r_buf_fread_at (bin->b, 0, (ut8*)&bin->hdr, "16c4il", 1); if (len == -1) { perror ("read (cache_header)"); return R_FALSE; @@ -62,7 +60,7 @@ struct r_bin_dyldcache_lib_t *r_bin_dyldcache_extract(struct r_bin_dyldcache_obj strncpy (ret[i].path, libname, sizeof (ret[j].path)); ret[j].size = libsz; ret[j].last = 0; - j = j+1; + j++; //printf("0x%08llx -> %i -> %s\n", liboff, libsz, libname); } ret[i].last = 1; @@ -81,7 +79,6 @@ void* r_bin_dyldcache_free(struct r_bin_dyldcache_obj_t* bin) { struct r_bin_dyldcache_obj_t* r_bin_dyldcache_new(const char* file) { struct r_bin_dyldcache_obj_t *bin; ut8 *buf; - if (!(bin = malloc(sizeof(struct r_bin_dyldcache_obj_t)))) return NULL; memset (bin, 0, sizeof (struct r_bin_dyldcache_obj_t)); diff --git a/libr/bin/p/bin_xtr_dyldcache.c b/libr/bin/p/bin_xtr_dyldcache.c index 4b1c4b597d..5103812673 100644 --- a/libr/bin/p/bin_xtr_dyldcache.c +++ b/libr/bin/p/bin_xtr_dyldcache.c @@ -28,7 +28,7 @@ static int extract(RBin *bin) { struct r_bin_dyldcache_lib_t *libs; int i; - if(!(bin->bin_obj = r_bin_dyldcache_new(bin->file))) + if(!(bin->bin_obj = r_bin_dyldcache_new (bin->file))) return 0; libs = r_bin_dyldcache_extract ((struct r_bin_dyldcache_obj_t*)bin->bin_obj); if (!libs) diff --git a/libr/core/cmd.c b/libr/core/cmd.c index 63f802d466..2cebcb6a9c 100644 --- a/libr/core/cmd.c +++ b/libr/core/cmd.c @@ -1806,7 +1806,7 @@ static int var_cmd(RCore *core, const char *str) { static void vmimport(RCore *core, int dir) { struct list_head *pos; list_for_each(pos, &core->vm->regs) { - struct r_vm_reg_t *r = list_entry(pos, struct r_vm_reg_t, list); + RVmReg *r = list_entry(pos, RVmReg, list); if (dir) { r_cons_printf ("ave %s=0x%"PFMT64x"\n", r->name, r->value); r_cons_printf ("f vm.%s=0x%"PFMT64x"\n", r->name, r->value); @@ -2154,6 +2154,7 @@ static int cmd_anal(void *data, const char *input) { " ; set register alias\n" " avr eax ; view register\n" " avr eax=33 ; set register value\n" + " avr* ; show registers as in flags\n" " avrt ; list valid register types\n" "Note: The prefix '\"' quotes the command and does not parses pipes and so\n"); else r_vm_cmd_reg (core->vm, input+2); @@ -2186,6 +2187,7 @@ static int cmd_anal(void *data, const char *input) { " avr ; show registers\n" " avx N ; execute N instructions from cur seek\n" " av- ; restart vm using asm.arch\n" + " av* ; show registers as in flags\n" " avr eax ; show register eax\n" " avrr eax ; set return register\n" // TODO .merge avrr and avrc " avrc eip esp ebp ; set basic cpu registers PC, SP, BP\n" diff --git a/libr/debug/p/drx.c b/libr/debug/p/drx.c new file mode 100644 index 0000000000..3df44b5b59 --- /dev/null +++ b/libr/debug/p/drx.c @@ -0,0 +1,167 @@ +#include + +/* -------------------- drx.h ------------------- */ +#define DRXN 7 +#define DR_STATUS 6 +#define DR_CONTROL 7 + +#define DR_LOCAL_ENABLE_SHIFT 0 /* Extra shift to the local enable bit. */ +#define DR_GLOBAL_ENABLE_SHIFT 1 /* Extra shift to the global enable bit. */ +#define DR_ENABLE_SIZE 2 /* Two enable bits per debug register. */ + +/* Fields reserved by Intel. This includes the GD (General Detect + Enable) flag, which causes a debug exception to be generated when a + MOV instruction accesses one of the debug registers. + + FIXME: My Intel manual says we should use 0xF800, not 0xFC00. */ +#define DR_CONTROL_RESERVED (0xFC00) + +#define I386_DR_CONTROL_MASK (~DR_CONTROL_RESERVED) + +#define DR_LOCAL_SLOWDOWN (0x100) +#define DR_GLOBAL_SLOWDOWN (0x200) + +/* DR7 fields */ +/* How many bits to skip in DR7 to get to R/W and LEN fields. */ +#define DR_CONTROL_SHIFT 16 +/* How many bits in DR7 per R/W and LEN field for each watchpoint. */ +#define DR_CONTROL_SIZE 4 + +#define DR_RW_EXECUTE (0x0) /* Break on instruction execution. */ +#define DR_RW_WRITE (0x1) /* Break on data writes. */ +#define DR_RW_IORW (0x2) /* Break on I/O reads or writes (not supported (2001) */ +#define DR_RW_READ (0x3) /* Break on data reads or writes. */ + +/* Debug registers' indices. */ +#define DR_NADDR 4 /* The number of debug address registers. */ +#define DR_STATUS 6 /* Index of debug status register (DR6). */ +#define DR_CONTROL 7 /* Index of debug control register (DR7). */ + +// is ut64 on 64 bitz ? +//#define drxt ut64 +#define drxt ut32 + +#define DR_LEN_1 (0<<2) /* 1-byte region watch or breakpoint. */ +#define DR_LEN_2 (1<<2) /* 2-byte region watch. */ +#define DR_LEN_4 (3<<2) /* 4-byte region watch. */ +#define DR_LEN_8 (2<<2) /* 8-byte region watch (AMD64). */ + +#define I386_DR_CONTROL_MASK (~DR_CONTROL_RESERVED) + +/* unused */ +#define I386_DR_VACANT(control, i) \ + ((control & (3 << (DR_ENABLE_SIZE * (i)))) == 0) +/* local/global */ +#define I386_DR_LOCAL_ENABLE(control, i) \ + control |= (1 << (DR_LOCAL_ENABLE_SHIFT + DR_ENABLE_SIZE * (i))) +#define I386_DR_GLOBAL_ENABLE(control, i) \ + control |= (1 << (DR_GLOBAL_ENABLE_SHIFT + DR_ENABLE_SIZE * (i))) +/* enable/disable */ +#define I386_DR_ENABLE(control, i) \ + control |= (3 << (DR_ENABLE_SIZE * (i))) +#define I386_DR_DISABLE(control, i) \ + control &= ~(3 << (DR_ENABLE_SIZE * (i))) + +#define I386_DR_SET_RW_LEN(control, i,rwlen) \ + do { \ + control &= ~(0x0f << (DR_CONTROL_SHIFT+DR_CONTROL_SIZE*(i))); \ + control |= ((rwlen) << (DR_CONTROL_SHIFT+DR_CONTROL_SIZE*(i))); \ + } while (0) +#define I386_DR_GET_RW_LEN(control, i) \ + ((control >> (DR_CONTROL_SHIFT + DR_CONTROL_SIZE * (i))) & 0x0f) + +/* ----------------------------- */ + +#if 0 +options are: + address + length + local/global + type (rwxi) + + +// DRX CHK + +int drx_check() { + return R_TRUE; +} +#endif + +int drx_set(drxt *drx, int n, ut64 addr, int len, int rwx, int global) { + ut32 control = drx[DR_CONTROL]; + if (n<0 || n>4) { + eprintf ("Invalid DRX index (0-4)\n"); + return R_FALSE; + } + switch (len) { + case 1: + len = 0; + break; + case 2: + len = 1<<2; + break; + case 4: + len = 3<<2; + break; + case 8: + len = 2<<2; // AMD64 only + break; + default: + eprintf ("Invalid DRX length\n"); + return R_FALSE; + } + I386_DR_SET_RW_LEN (control, n, len); + if (global) { + I386_DR_GLOBAL_ENABLE (control, n); + control |= DR_GLOBAL_SLOWDOWN; + } else { + I386_DR_LOCAL_ENABLE (control, n); + control |= DR_LOCAL_SLOWDOWN; + } + control &= I386_DR_CONTROL_MASK; + drx[n] = addr; + drx[DR_CONTROL] = control; +} + +ut64 drx_get(drxt *drx, int n, int *rwx, int *len, int *global) { + int ret = I386_DR_GET_RW_LEN (drx[DR_CONTROL], n); + if (global) *global = drx[DR_CONTROL] & DR_GLOBAL_SLOWDOWN; + if (len) *len = (ret & 0xf)>>2; + if (rwx) *rwx = ret & 0x3; + return (ut64)drx[n]; +} + +int drx_next(drxt *drx) { + int i; + for(i=0; i<4; i++) + if (!drx[i]) + return i; + return -1; +} + +void drx_list(drxt *drx) { + ut64 addr; + int i, type, len, g; + for(i=0; i<4; i++) { + addr = drx_get (drx, i, &type, &len, &g); + printf ("DR%d %c%c%c%c 0x%08llx %d\n", i, + g?'g':'l', + (type&DR_RW_READ)? 'r':'-', + (type&DR_RW_WRITE)? 'w':'-', + (type&DR_RW_EXECUTE)? 'x':'-', + addr, len); + } +} + +void drx_init(drxt *r) { + memset (r, 0, sizeof (drxt)*DRXN); +} + +#if MAIN +int main() { + drxt regs[DRXN]; + drx_init (regs); + drx_set (regs, 1, 0x8048000, 1, DR_RW_EXECUTE, 0); + drx_list (regs); +} +#endif diff --git a/libr/vm/reg.c b/libr/vm/reg.c index 524599014e..59ab0f293f 100644 --- a/libr/vm/reg.c +++ b/libr/vm/reg.c @@ -142,19 +142,21 @@ R_API int r_vm_cmd_reg(struct r_vm_t *vm, const char *_str) { len = strlen (_str)+1; str = alloca (len); - memcpy (str, _str, len); + memcpy (str, _str, len); // XXX: suboptimal - if (str==NULL || str[0]=='\0') { - /* show all registers */ + switch(*str) { + case '*': + r_vm_print (vm, -2); + return 0; + case '\0': r_vm_print (vm, -1); return 0; - } - if (str[0]=='o') { + case 'o': r_vm_cmd_op (vm, str+2); return 0; } - strcpy(str, str+1); - switch(str[0]) { + str++; + switch (*str) { case 'r': r_vm_setup_ret (vm, str+2); break; @@ -205,11 +207,11 @@ R_API int r_vm_cmd_reg(struct r_vm_t *vm, const char *_str) { // avr-* for(str=str+1;str&&*str==' ';str=str+1); if (str[0]=='*') - INIT_LIST_HEAD(&vm->regs); // XXX Memory leak - else r_vm_reg_del(vm, str); + INIT_LIST_HEAD (&vm->regs); // XXX Memory leak + else r_vm_reg_del (vm, str); break; case 'f': - r_vm_setup_flags(vm, str+2); + r_vm_setup_flags (vm, str+2); break; default: for(;str&&*str==' ';str=str+1); @@ -240,7 +242,7 @@ R_API ut64 r_vm_reg_get(struct r_vm_t *vm, const char *name) { int len; if (!name) return 0LL; - len = strlen(name); + len = strlen (name); if (name[len-1]==']') len--; @@ -252,7 +254,6 @@ R_API ut64 r_vm_reg_get(struct r_vm_t *vm, const char *name) { r_vm_eval(vm, r->get); //vm_op_eval(r->get); vm->rec = NULL; - return r->value; } return r->value; } diff --git a/libr/vm/vm.c b/libr/vm/vm.c index 695c92bf12..acb5f01423 100644 --- a/libr/vm/vm.c +++ b/libr/vm/vm.c @@ -18,8 +18,7 @@ static ut64 r_vm_get_value(RVm *vm, const char *str) { ret = r_vm_reg_get (vm, vm->cpu.pc); arch_aop (ret , config.block, &aop); return aop.length; - } else // $$ - return config.seek; + } else return config.seek; // $$ #endif } diff --git a/swig/python/test-r_cons.py b/swig/python/test-r_cons.py index a66abc256c..b2f2d69e83 100644 --- a/swig/python/test-r_cons.py +++ b/swig/python/test-r_cons.py @@ -20,7 +20,6 @@ con.any_key() con.clear() print dir(RCons.is_html) -print RCons.is_html.getter(0) print "IS HTML %d"%int(RCons.is_html) con.printf(Color_RED + "Hello "+Color_GREEN + "World\n" + Color_RESET) con.flush();