/* radare - LGPL - Copyright 2008-2010 pancake */ #include "r_vm.h" /* TODO: use r_reg here..instead of reimplement the fucking same all the time */ static char *unkreg = "(unk)"; /* static */ static struct r_vm_reg_type r_vm_reg_types[] = { { R_VMREG_BIT, "bit" }, { R_VMREG_INT64, "int64" }, { R_VMREG_INT32, "int32" }, { R_VMREG_INT16, "int16" }, { R_VMREG_INT8, "int8" }, { R_VMREG_FLOAT32, "float32" }, { R_VMREG_FLOAT64, "float64" }, { 0, NULL } }; R_API void r_vm_reg_type_list() { struct r_vm_reg_type *p = r_vm_reg_types; while (p && p->str) { if (p->str==NULL) break; printf(" .%s\n", p->str); p++; } } R_API const char *r_vm_reg_type(int type) { struct r_vm_reg_type *p = r_vm_reg_types; while (p && p->str) { if (p->type == type) return p->str; p++; } return unkreg; } R_API int r_vm_reg_type_i(const char *str) { struct r_vm_reg_type *p = r_vm_reg_types; while (p && p->str) { if (!strcmp(str, p->str)) return p->type; p++; } return -1; } R_API int r_vm_reg_del(RVm *vm, const char *name) { struct list_head *pos; list_for_each(pos, &vm->regs) { struct r_vm_reg_t *r = list_entry(pos, struct r_vm_reg_t, list); if (!strcmp(name, r->name)) { list_del(&r->list); return R_FALSE; } } return R_TRUE; } R_API int r_vm_reg_set(RVm *vm, const char *name, ut64 value) { struct list_head *pos; if (name) list_for_each(pos, &vm->regs) { struct r_vm_reg_t *r = list_entry(pos, struct r_vm_reg_t, list); if (!strcmp(name, r->name)) { r->value = value; if (vm->rec == NULL && r->set != NULL) { vm->rec = r; r_vm_eval(vm, r->set); vm->rec = NULL; } return R_TRUE; } } return R_FALSE; } R_API int r_vm_reg_alias_list(RVm *vm) { struct r_vm_reg_t *reg; struct list_head *pos; int len,space; eprintf ("Register alias:\n"); list_for_each (pos, &vm->regs) { reg= list_entry (pos, struct r_vm_reg_t, list); if (reg->get == NULL && reg->set == NULL) continue; len = strlen(reg->name)+1; printf("%s:", reg->name); if (len>=R_VM_ALEN) { space = R_VM_ALEN; printf("\n"); } else space = R_VM_ALEN-len; eprintf ("%*cget = %s\n%*cset = %s\n", space, ' ', reg->get, R_VM_ALEN,' ', reg->set); } return 0; } R_API int r_vm_reg_alias(RVm *vm, const char *name, const char *get, const char *set) { struct r_vm_reg_t *reg; struct list_head *pos; list_for_each(pos, &vm->regs) { reg = list_entry(pos, struct r_vm_reg_t, list); if (!strcmp(name, reg->name)) { free(reg->get); reg->get = NULL; if (get) reg->get = strdup(get); free(reg->set); reg->set = NULL; if (set) reg->set = strdup(set); return 1; } } eprintf ("Register '%s' not defined.\n", name); return 0; } R_API int r_vm_cmd_eval(RVm *vm, const char *cmd) { char *next; do { next = strchr (cmd,'\n'); if (next) { *next=0; next++; } if (strlen (cmd)>2 && !memcmp (cmd, "av", 2)) r_vm_cmd_reg (vm, cmd+2); cmd = next; } while (next); return R_TRUE; } R_API int r_vm_cmd_reg(RVm *vm, const char *_str) { char *str, ostr[128], *ptr; str = ostr; strncpy (str, _str, sizeof (ostr)-1); switch(*str) { case '*': r_vm_print (vm, -2); return 0; case '\0': r_vm_print (vm, -1); return 0; case 'o': r_vm_cmd_op (vm, str+2); return 0; } str++; switch (*str) { case 'r': r_vm_setup_ret (vm, str+2); break; case 'c': { char *sp, *bp, *pc = str+2; sp = strchr(pc, ' '); if (!sp) return 0; *sp=0;sp++; bp = strchr(sp, ' '); if (!sp) return 0; *bp=0;bp++; r_vm_setup_cpu (vm, pc, sp, bp); } break; case 'a': if (str[1]==' ') { char *get,*set; get = strchr (str+2, ' '); if (get) { get[0]='\0'; get = get+1; set = strchr (get, ' '); if (set) { *set = '\0'; set++; r_vm_reg_alias (vm, str+2, get, set); } } } else r_vm_reg_alias_list (vm); break; case 't': r_vm_reg_type_list (vm); break; case '+': // add register // avr+ eax int32 for (str=str+1;str&&*str==' ';str=str+1); ptr = strchr(str, ' '); if (ptr) { ptr[0]='\0'; r_vm_reg_add (vm, str, r_vm_reg_type_i(ptr+1), 0); } else r_vm_reg_add (vm, str, R_VMREG_INT32, 0); break; case '-': // rm register // avr- eax // 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); break; case 'f': r_vm_setup_flags (vm, str+2); break; default: for (;str && *str==' '; str++); ptr = strchr (str, '='); if (ptr) { //vm_eval(str); r_vm_op_eval (vm, str); #if 0 /* set register value */ ptr[0]='\0'; vm_eval_eq(str, ptr+1); ptr[0]='='; #endif } else { if (*str=='.') r_vm_print (vm, r_vm_reg_type_i(str+1)); else eprintf ("%s = 0x%08"PFMT64x"\n", str, r_vm_reg_get(vm, str)); } } return 0; } R_API ut64 r_vm_reg_get(RVm *vm, const char *name) { struct list_head *pos; int len; if (!name) return 0LL; len = strlen (name); if (name[len-1]==']') len--; list_for_each (pos, &vm->regs) { RVmReg *r = list_entry(pos, struct r_vm_reg_t, list); if (!strncmp (name, r->name, len)) { if (vm->rec==NULL && r->get != NULL) { vm->rec = r; r_vm_eval(vm, r->get); //vm_op_eval(r->get); vm->rec = NULL; } return r->value; } } return -1LL; }