mirror of
https://github.com/radareorg/radare2.git
synced 2024-12-03 19:01:31 +00:00
8f9dbbd0d1
* Fix lock when using 'r2 -d' * Invalid program name results in error, not warning
256 lines
5.2 KiB
C
256 lines
5.2 KiB
C
/* radare - LGPL - Copyright 2008-2010 pancake<nopcode.org> */
|
|
|
|
#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;
|
|
}
|