* Fix build and linkage of r_vm

- Added dummy test program for r_vm
This commit is contained in:
pancake/fluendo 2009-07-16 12:38:49 +02:00
parent 6f0ddc5247
commit 564e11975a
11 changed files with 116 additions and 78 deletions

View File

@ -71,7 +71,7 @@ R_API const char *r_str_ansi_chrn(const char *str, int n);
R_API int r_str_ansi_len(const char *str); R_API int r_str_ansi_len(const char *str);
R_API int r_str_word_count(const char *string); R_API int r_str_word_count(const char *string);
R_API int r_str_word_set0(char *str); R_API int r_str_word_set0(char *str);
R_API const char *r_str_word_get0(const char *str, int idx); R_API char *r_str_word_get0(char *str, int idx);
R_API char *r_str_word_get_first(const char *string); R_API char *r_str_word_get_first(const char *string);
R_API char *r_str_chop(char *str); R_API char *r_str_chop(char *str);
R_API const char *r_str_chop_ro(const char *str); R_API const char *r_str_chop_ro(const char *str);

View File

@ -30,8 +30,8 @@ struct r_vm_reg_t {
}; };
struct r_vm_op_t { struct r_vm_op_t {
const char opcode[32]; char opcode[32];
const char code[1024]; char code[1024];
struct list_head list; struct list_head list;
}; };
@ -69,57 +69,68 @@ struct r_vm_t {
ut8 *vm_stack; ut8 *vm_stack;
struct list_head mmu_cache; struct list_head mmu_cache;
int realio; int realio;
/* io callbacks */
int (*read)(void *user, ut64 addr, ut8 *buf, int len);
int (*write)(void *user, ut64 addr, ut8 *buf, int len);
void *user;
}; };
ut64 vm_reg_get(const char *name); R_API ut64 vm_reg_get(const char *name);
void vm_stack_push(ut64 _val); R_API void vm_stack_push(ut64 _val);
#if 0 #if 0
static ut64 r_vm_get_value(struct r_vm_t *vm, const char *str); static ut64 r_vm_get_value(struct r_vm_t *vm, const char *str);
static ut64 r_vm_get_math(struct r_vm_t *vm, const char *str); static ut64 r_vm_get_math(struct r_vm_t *vm, const char *str);
#endif #endif
void r_vm_print(struct r_vm_t *vm, int type); R_API void r_vm_print(struct r_vm_t *vm, int type);
int r_vm_import(struct r_vm_t *vm, int in_vm); R_API int r_vm_import(struct r_vm_t *vm, int in_vm);
void r_vm_cpu_call(struct r_vm_t *vm, ut64 addr); R_API void r_vm_cpu_call(struct r_vm_t *vm, ut64 addr);
int r_vm_init(struct r_vm_t *vm, int init); R_API int r_vm_init(struct r_vm_t *vm, int init);
int r_vm_eval_cmp(struct r_vm_t *vm, const char *str); R_API int r_vm_eval_cmp(struct r_vm_t *vm, const char *str);
int r_vm_eval_eq(struct r_vm_t *vm, const char *str, const char *val); R_API int r_vm_eval_eq(struct r_vm_t *vm, const char *str, const char *val);
int r_vm_eval_single(struct r_vm_t *vm, const char *str); R_API int r_vm_eval_single(struct r_vm_t *vm, const char *str);
int r_vm_eval(struct r_vm_t *vm, const char *str); R_API int r_vm_eval(struct r_vm_t *vm, const char *str);
int r_vm_eval_file(struct r_vm_t *vm, const char *str); R_API int r_vm_eval_file(struct r_vm_t *vm, const char *str);
int r_vm_emulate(struct r_vm_t *vm, int n); R_API int r_vm_emulate(struct r_vm_t *vm, int n);
int r_vm_cmd_reg(struct r_vm_t *vm, const char *_str); R_API int r_vm_cmd_reg(struct r_vm_t *vm, const char *_str);
int r_vm_op_add(struct r_vm_t *vm, const char *op, const char *str); R_API int r_vm_op_add(struct r_vm_t *vm, const char *op, const char *str);
int r_vm_op_eval(struct r_vm_t *vm, const char *str); R_API int r_vm_op_eval(struct r_vm_t *vm, const char *str);
int r_vm_op_cmd(struct r_vm_t *vm, const char *op); R_API int r_vm_op_cmd(struct r_vm_t *vm, const char *op);
/* reg */ /* reg */
void r_vm_reg_type_list(); R_API void r_vm_reg_type_list();
int r_vm_reg_add(struct r_vm_t *vm, const char *name, int type, ut64 value); R_API int r_vm_reg_add(struct r_vm_t *vm, const char *name, int type, ut64 value);
ut64 r_vm_reg_get(struct r_vm_t *vm, const char *name); R_API ut64 r_vm_reg_get(struct r_vm_t *vm, const char *name);
int r_vm_reg_alias_list(struct r_vm_t *vm); R_API int r_vm_reg_alias_list(struct r_vm_t *vm);
const char *r_vm_reg_type(int type); R_API const char *r_vm_reg_type(int type);
const int r_vm_reg_type_i(const char *str); R_API const int r_vm_reg_type_i(const char *str);
int r_vm_reg_del(struct r_vm_t *vm, const char *name); R_API int r_vm_reg_del(struct r_vm_t *vm, const char *name);
int r_vm_reg_set(struct r_vm_t *vm, const char *name, ut64 value); R_API int r_vm_reg_set(struct r_vm_t *vm, const char *name, ut64 value);
int r_vm_reg_alias(struct r_vm_t *vm, const char *name, const char *get, const char *set); R_API int r_vm_reg_alias(struct r_vm_t *vm, const char *name, const char *get, const char *set);
/* cfg */ /* cfg */
R_API void r_vm_setup_flags(struct r_vm_t *vm, const char *zf);
void r_vm_setup_flags(struct r_vm_t *vm, const char *zf); R_API void r_vm_setup_cpu(struct r_vm_t *vm, const char *eip, const char *esp, const char *ebp);
void r_vm_setup_cpu(struct r_vm_t *vm, const char *eip, const char *esp, const char *ebp); R_API void r_vm_setup_fastcall(struct r_vm_t *vm, const char *eax, const char *ebx, const char *ecx, const char *edx);
void r_vm_setup_fastcall(struct r_vm_t *vm, const char *eax, const char *ebx, const char *ecx, const char *edx); R_API void r_vm_setup_ret(struct r_vm_t *vm, const char *eax);
void r_vm_setup_ret(struct r_vm_t *vm, const char *eax);
/* stack */ /* stack */
void r_vm_stack_push(struct r_vm_t *vm, ut64 _val); R_API void r_vm_stack_push(struct r_vm_t *vm, ut64 _val);
void r_vm_stack_pop(struct r_vm_t *vm, const char *reg); R_API void r_vm_stack_pop(struct r_vm_t *vm, const char *reg);
/* mmu */ /* mmu */
int r_vm_mmu_cache_write(struct r_vm_t *vm, ut64 addr, ut8 *buf, int len); R_API int r_vm_mmu_cache_write(struct r_vm_t *vm, ut64 addr, ut8 *buf, int len);
int r_vm_mmu_cache_read(struct r_vm_t *vm, ut64 addr, ut8 *buf, int len); R_API int r_vm_mmu_cache_read(struct r_vm_t *vm, ut64 addr, ut8 *buf, int len);
int r_vm_mmu_read(struct r_vm_t *vm, ut64 off, ut8 *data, int len); R_API int r_vm_mmu_read(struct r_vm_t *vm, ut64 off, ut8 *data, int len);
int r_vm_mmu_write(struct r_vm_t *vm, ut64 off, ut8 *data, int len); R_API int r_vm_mmu_write(struct r_vm_t *vm, ut64 off, ut8 *data, int len);
int r_vm_mmu_real(struct r_vm_t *vm, int set); R_API int r_vm_mmu_real(struct r_vm_t *vm, int set);
R_API void r_vm_mmu_set_io(struct r_vm_t *vm,
int (*read)(void *user, ut64 addr, ut8 *buf, int len),
int (*write)(void *user, ut64 addr, ut8 *buf, int len),
void *user);
/* extra */
int r_vm_cmd_op_help();
int r_vm_op_list(struct r_vm_t *vm);
#endif #endif

View File

@ -65,7 +65,7 @@ R_API int r_str_word_set0(char *str)
return i; return i;
} }
R_API const char *r_str_word_get0(const char *str, int idx) R_API char *r_str_word_get0(char *str, int idx)
{ {
int i; int i;
const char *ptr = str; const char *ptr = str;
@ -78,11 +78,10 @@ R_API const char *r_str_word_get0(const char *str, int idx)
R_API int r_str_word_count(const char *string) R_API int r_str_word_count(const char *string)
{ {
char *text = (char *)string; char *text, *tmp;
char *tmp = (char *)string;
int word = 0; int word = 0;
for(;(*text)&&(isseparator(*text));text=text+1); for(text=tmp=string;(*text)&&(isseparator(*text));text=text+1);
for(word = 0; *text; word++) { for(word = 0; *text; word++) {
for(;*text && !isseparator(*text);text = text +1); for(;*text && !isseparator(*text);text = text +1);

View File

@ -1,5 +1,6 @@
NAME=r_vm NAME=r_vm
DEPS=r_util
OBJ=vm.o mmu.o reg.o extra.o OBJ=vm.o mmu.o reg.o extra.o setup.o stack.o op.o
include ../rules.mk include ../rules.mk

View File

@ -2,7 +2,7 @@
#include "r_vm.h" #include "r_vm.h"
int r_vm_mmu_cache_write(struct r_vm_t *vm, ut64 addr, ut8 *buf, int len) R_API int r_vm_mmu_cache_write(struct r_vm_t *vm, ut64 addr, ut8 *buf, int len)
{ {
struct r_vm_change_t *ch = MALLOC_STRUCT(struct r_vm_change_t); struct r_vm_change_t *ch = MALLOC_STRUCT(struct r_vm_change_t);
ch->from = addr; ch->from = addr;
@ -13,7 +13,7 @@ int r_vm_mmu_cache_write(struct r_vm_t *vm, ut64 addr, ut8 *buf, int len)
return 0; return 0;
} }
int r_vm_mmu_cache_read(struct r_vm_t *vm, ut64 addr, ut8 *buf, int len) R_API int r_vm_mmu_cache_read(struct r_vm_t *vm, ut64 addr, ut8 *buf, int len)
{ {
struct r_vm_change_t *c; struct r_vm_change_t *c;
struct list_head *pos; struct list_head *pos;
@ -29,20 +29,33 @@ int r_vm_mmu_cache_read(struct r_vm_t *vm, ut64 addr, ut8 *buf, int len)
return 0; return 0;
} }
int r_vm_mmu_read(struct r_vm_t *vm, ut64 off, ut8 *data, int len) R_API void r_vm_mmu_set_io(struct r_vm_t *vm,
int (*read)(void *user, ut64 addr, ut8 *buf, int len),
int (*write)(void *user, ut64 addr, ut8 *buf, int len),
void *user)
{
vm->read = read;
vm->write = write;
vm->user = user;
}
R_API int r_vm_mmu_read(struct r_vm_t *vm, ut64 off, ut8 *data, int len)
{ {
if (!vm->realio && r_vm_mmu_cache_read(vm, off, data, len)) if (!vm->realio && r_vm_mmu_cache_read(vm, off, data, len))
return len; return len;
return r_io_read_at(vm, off, data, len); if (vm->read)
return vm->read(vm->user, off, data, len);
return -1;
} }
int r_vm_mmu_write(struct r_vm_t *vm, ut64 off, ut8 *data, int len) R_API int r_vm_mmu_write(struct r_vm_t *vm, ut64 off, ut8 *data, int len)
{ {
if (!vm->realio) if (!vm->realio)
return r_vm_mmu_cache_write(vm, off, data, len); return r_vm_mmu_cache_write(vm, off, data, len);
fprintf(stderr, "vm_mmu_write!\n");
// XXX: callback for write-at should be userdefined // XXX: callback for write-at should be userdefined
return r_io_write_at(vm, off, data, len); if (vm->write)
return vm->write(vm->user, off, data, len);
return -1;
} }
int r_vm_mmu_real(struct r_vm_t *vm, int set) int r_vm_mmu_real(struct r_vm_t *vm, int set)

View File

@ -16,20 +16,18 @@ int r_vm_op_add(struct r_vm_t *vm, const char *op, const char *str)
int r_vm_op_eval(struct r_vm_t *vm, const char *str) int r_vm_op_eval(struct r_vm_t *vm, const char *str)
{ {
char *p,*s; struct list_head *pos;
char *p, *s, *arg0;
int j, k, len = strlen(str)+256; int j, k, len = strlen(str)+256;
int nargs = 0; int nargs = 0;
char *arg0;
// eprintf("vmopeval(%s)\n", str);
p = alloca(len); p = alloca(len);
s = alloca(len); s = alloca(len);
memcpy(p, str, len); memcpy(p, str, len);
memcpy(s, str, len); memcpy(s, str, len);
struct list_head *pos; nargs = r_str_word_set0(s);
nargs = set0word(s); arg0 = r_str_word_get0(s, 0);
arg0 = get0word(s,0);
list_for_each(pos, &vm->ops) { list_for_each(pos, &vm->ops) {
struct r_vm_op_t *o = list_entry(pos, struct r_vm_op_t, list); struct r_vm_op_t *o = list_entry(pos, struct r_vm_op_t, list);
@ -68,7 +66,7 @@ int r_vm_op_eval(struct r_vm_t *vm, const char *str)
} }
#endif #endif
if (str[j]>='0' && str[j]<='9') { if (str[j]>='0' && str[j]<='9') {
const char *w = get0word(s,str[j]-'0'); const char *w = r_str_word_get0(s, str[j]-'0');
if (w != NULL) { if (w != NULL) {
strcpy(p+k, w); strcpy(p+k, w);
k += strlen(w)-1; k += strlen(w)-1;
@ -79,8 +77,7 @@ int r_vm_op_eval(struct r_vm_t *vm, const char *str)
p[k]='\0'; p[k]='\0';
} }
} }
return r_vm_eval(vm, p);
return vm_eval(p);
} }
/* TODO : Allow to remove and so on */ /* TODO : Allow to remove and so on */
@ -97,6 +94,6 @@ int r_vm_op_cmd(struct r_vm_t *vm, const char *op)
ptr[0]='\0'; ptr[0]='\0';
eprintf("vm: opcode '%s' added\n", cmd); eprintf("vm: opcode '%s' added\n", cmd);
r_vm_op_add(vm, cmd, ptr+1); r_vm_op_add(vm, cmd, ptr+1);
} else vm_cmd_op_help(); } else r_vm_cmd_op_help();
return 0; return 0;
} }

View File

@ -196,7 +196,7 @@ int r_vm_cmd_reg(struct r_vm_t *vm, const char *_str)
r_vm_print(vm, r_vm_reg_type_i(str+1)); r_vm_print(vm, r_vm_reg_type_i(str+1));
} else { } else {
/* show single registers */ /* show single registers */
printf("%s = 0x%08llx\n", str, vm_reg_get(str)); printf("%s = 0x%08llx\n", str, r_vm_reg_get(vm, str));
} }
} }
} }

View File

@ -7,18 +7,18 @@ void r_vm_stack_push(struct r_vm_t *vm, ut64 _val)
{ {
// XXX determine size of stack here // XXX determine size of stack here
// XXX do not write while emulating zomfg // XXX do not write while emulating zomfg
// XXX we need a way to define the size of registers to grow/shrink the stack properly
ut32 val = _val; ut32 val = _val;
vm_reg_set(vm, vm_cpu.sp, vm_reg_get(vm, vm_cpu.sp)+4); r_vm_reg_set(vm, vm->cpu.sp, r_vm_reg_get(vm, vm->cpu.sp)+4);
vm_mmu_write(vm, vm_reg_get(vm, vm_cpu.sp), &val, 4); r_vm_mmu_write(vm, r_vm_reg_get(vm, vm->cpu.sp), (void *)&val, 4);
} }
void r_vm_stack_pop(struct r_vm_t *vm, const char *reg) void r_vm_stack_pop(struct r_vm_t *vm, const char *reg)
{ {
ut32 val = 0; ut32 val = 0;
if (vm_mmu_read(vm_reg_get(vm, vm->cpu.sp), &val, 4)) if (r_vm_mmu_read(vm, r_vm_reg_get(vm, vm->cpu.sp), (void *)&val, 4))
return; return;
//printf("POP (%s)\n", reg); r_vm_mmu_read(vm, r_vm_reg_get(vm, vm->cpu.sp), (void *)&val, 4);
vm_mmu_read(vm, vm_reg_get(vm, vm->cpu.sp), &val, 4); r_vm_reg_set(vm, reg, val);
vm_reg_set(vm, reg, val); r_vm_reg_set(vm, vm->cpu.sp, r_vm_reg_get(vm, vm->cpu.sp)-4);
vm_reg_set(vm_cpu.sp, vm_reg_get(vm, vm->cpu.sp)-4);
} }

5
libr/vm/t/Makefile Normal file
View File

@ -0,0 +1,5 @@
OBJ=test.o
BIN=test
BINDEPS=r_vm
include ../../rules.mk

9
libr/vm/t/test.c Normal file
View File

@ -0,0 +1,9 @@
#include <r_vm.h>
int main()
{
struct r_vm_t vm;
r_vm_init(&vm, 1);
/* ... TODO ... */
return 0;
}

View File

@ -175,7 +175,7 @@ R_API int r_vm_import(struct r_vm_t *vm, int in_vm)
R_API void r_vm_cpu_call(struct r_vm_t *vm, ut64 addr) R_API void r_vm_cpu_call(struct r_vm_t *vm, ut64 addr)
{ {
/* x86 style */ /* x86 style */
r_vm_stack_push(vm, vm_reg_get(vm->cpu.pc)); r_vm_stack_push(vm, r_vm_reg_get(vm, vm->cpu.pc));
r_vm_reg_set(vm, vm->cpu.pc, addr); r_vm_reg_set(vm, vm->cpu.pc, addr);
// XXX this should be the next instruction after pc (we need insn length here) // XXX this should be the next instruction after pc (we need insn length here)
} }
@ -192,6 +192,7 @@ R_API int r_vm_init(struct r_vm_t *vm, int init)
INIT_LIST_HEAD(&vm->regs); INIT_LIST_HEAD(&vm->regs);
INIT_LIST_HEAD(&vm->ops); INIT_LIST_HEAD(&vm->ops);
memset(&vm->cpu, '\0', sizeof(struct r_vm_cpu_t)); memset(&vm->cpu, '\0', sizeof(struct r_vm_cpu_t));
vm->user = vm->read = vm->write = NULL;
} }
//vm_mmu_real(vm, config_get_i("vm.realio")); //vm_mmu_real(vm, config_get_i("vm.realio"));
@ -247,8 +248,10 @@ R_API int r_vm_init(struct r_vm_t *vm, int init)
//vm_setup_copy("esi", "edi"); //vm_setup_copy("esi", "edi");
r_vm_setup_ret(vm, "eax"); r_vm_setup_ret(vm, "eax");
// TODO: do the same for fpregs and mmregs // TODO: do the same for fpregs and mmregs
#if 0
if (init) // XXX if (init) // XXX
r_vm_arch_x86_init(vm); r_vm_arch_x86_init(vm);
#endif
break; break;
#if 0 #if 0
case ARCH_MIPS: case ARCH_MIPS:
@ -326,7 +329,7 @@ R_API int r_vm_eval_eq(struct r_vm_t *vm, const char *str, const char *val)
} else { } else {
r_vm_mmu_read(vm, off, (ut8*)&_int32, 4); r_vm_mmu_read(vm, off, (ut8*)&_int32, 4);
//off = r_vm_get_math(val); //off = r_vm_get_math(val);
r_vm_mmu_write(vm, off, (const ut8*)&_int32, 4); r_vm_mmu_write(vm, off, (void*)&_int32, 4);
} }
} else { } else {
// [0x804800] = eax // [0x804800] = eax
@ -454,20 +457,20 @@ R_API int r_vm_eval_single(struct r_vm_t *vm, const char *str)
if((!memcmp(ptr, "call ", 4)) if((!memcmp(ptr, "call ", 4))
|| (!memcmp(ptr, "jmp ", 4))){ || (!memcmp(ptr, "jmp ", 4))){
if (ptr[0]=='c') if (ptr[0]=='c')
r_vm_stack_push(vm, vm->cpu.pc); r_vm_stack_push(vm, r_vm_get_value(vm, vm->cpu.pc));
printf("CALL(%s)\n", ptr+4); printf("CALL(%s)\n", ptr+4);
r_vm_reg_set(vm, vm->cpu.pc, r_vm_get_value(vm, ptr+4)); r_vm_reg_set(vm, vm->cpu.pc, r_vm_get_value(vm, ptr+4));
} else } else
if (!memcmp(ptr, "jz ", 3)){ if (!memcmp(ptr, "jz ", 3)){
if (vm_reg_get(ptr+3)==0) if (r_vm_reg_get(vm, ptr+3)==0)
r_vm_reg_set(vm, vm->cpu.pc, r_vm_get_value(vm, ptr+3)); r_vm_reg_set(vm, vm->cpu.pc, r_vm_get_value(vm, ptr+3));
} else } else
if (!memcmp(ptr, "jnz ", 4)){ if (!memcmp(ptr, "jnz ", 4)){
if (vm_reg_get(ptr+4)==0) if (r_vm_reg_get(vm, ptr+4)==0)
r_vm_reg_set(vm, vm->cpu.pc, r_vm_get_value(vm, ptr+4)); r_vm_reg_set(vm, vm->cpu.pc, r_vm_get_value(vm, ptr+4));
} else } else
if (!memcmp(ptr, "push ", 5)) { if (!memcmp(ptr, "push ", 5)) {
r_vm_stack_push(vm, str+5); r_vm_stack_push(vm, r_vm_get_value(vm, str+5));
} else } else
if (!memcmp(str, "pop ", 4)) { if (!memcmp(str, "pop ", 4)) {
r_vm_stack_pop(vm, str+5); r_vm_stack_pop(vm, str+5);