* Fix build and linkage of r_vm
- Added dummy test program for r_vm
This commit is contained in:
parent
6f0ddc5247
commit
564e11975a
|
@ -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_word_count(const char *string);
|
||||
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_chop(char *str);
|
||||
R_API const char *r_str_chop_ro(const char *str);
|
||||
|
|
|
@ -30,8 +30,8 @@ struct r_vm_reg_t {
|
|||
};
|
||||
|
||||
struct r_vm_op_t {
|
||||
const char opcode[32];
|
||||
const char code[1024];
|
||||
char opcode[32];
|
||||
char code[1024];
|
||||
struct list_head list;
|
||||
};
|
||||
|
||||
|
@ -69,57 +69,68 @@ struct r_vm_t {
|
|||
ut8 *vm_stack;
|
||||
struct list_head mmu_cache;
|
||||
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);
|
||||
void vm_stack_push(ut64 _val);
|
||||
R_API ut64 vm_reg_get(const char *name);
|
||||
R_API void vm_stack_push(ut64 _val);
|
||||
|
||||
#if 0
|
||||
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);
|
||||
#endif
|
||||
void r_vm_print(struct r_vm_t *vm, int type);
|
||||
int r_vm_import(struct r_vm_t *vm, int in_vm);
|
||||
void r_vm_cpu_call(struct r_vm_t *vm, ut64 addr);
|
||||
int r_vm_init(struct r_vm_t *vm, int init);
|
||||
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);
|
||||
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);
|
||||
int r_vm_eval_file(struct r_vm_t *vm, const char *str);
|
||||
int r_vm_emulate(struct r_vm_t *vm, int n);
|
||||
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);
|
||||
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 void r_vm_print(struct r_vm_t *vm, int type);
|
||||
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 int r_vm_init(struct r_vm_t *vm, int init);
|
||||
R_API int r_vm_eval_cmp(struct r_vm_t *vm, const char *str);
|
||||
R_API int r_vm_eval_eq(struct r_vm_t *vm, const char *str, const char *val);
|
||||
R_API int r_vm_eval_single(struct r_vm_t *vm, const char *str);
|
||||
R_API int r_vm_eval(struct r_vm_t *vm, const char *str);
|
||||
R_API int r_vm_eval_file(struct r_vm_t *vm, const char *str);
|
||||
R_API int r_vm_emulate(struct r_vm_t *vm, int n);
|
||||
R_API int r_vm_cmd_reg(struct r_vm_t *vm, const char *_str);
|
||||
R_API int r_vm_op_add(struct r_vm_t *vm, const char *op, const char *str);
|
||||
R_API int r_vm_op_eval(struct r_vm_t *vm, const char *str);
|
||||
R_API int r_vm_op_cmd(struct r_vm_t *vm, const char *op);
|
||||
|
||||
/* reg */
|
||||
void r_vm_reg_type_list();
|
||||
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);
|
||||
int r_vm_reg_alias_list(struct r_vm_t *vm);
|
||||
const char *r_vm_reg_type(int type);
|
||||
const int r_vm_reg_type_i(const char *str);
|
||||
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);
|
||||
int r_vm_reg_alias(struct r_vm_t *vm, const char *name, const char *get, const char *set);
|
||||
R_API void r_vm_reg_type_list();
|
||||
R_API int r_vm_reg_add(struct r_vm_t *vm, const char *name, int type, ut64 value);
|
||||
R_API ut64 r_vm_reg_get(struct r_vm_t *vm, const char *name);
|
||||
R_API int r_vm_reg_alias_list(struct r_vm_t *vm);
|
||||
R_API const char *r_vm_reg_type(int type);
|
||||
R_API const int r_vm_reg_type_i(const char *str);
|
||||
R_API int r_vm_reg_del(struct r_vm_t *vm, const char *name);
|
||||
R_API int r_vm_reg_set(struct r_vm_t *vm, const char *name, ut64 value);
|
||||
R_API int r_vm_reg_alias(struct r_vm_t *vm, const char *name, const char *get, const char *set);
|
||||
|
||||
/* cfg */
|
||||
|
||||
void r_vm_setup_flags(struct r_vm_t *vm, const char *zf);
|
||||
void r_vm_setup_cpu(struct r_vm_t *vm, const char *eip, const char *esp, const char *ebp);
|
||||
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_ret(struct r_vm_t *vm, const char *eax);
|
||||
R_API 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);
|
||||
R_API 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);
|
||||
|
||||
/* stack */
|
||||
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_push(struct r_vm_t *vm, ut64 _val);
|
||||
R_API void r_vm_stack_pop(struct r_vm_t *vm, const char *reg);
|
||||
|
||||
/* mmu */
|
||||
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);
|
||||
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);
|
||||
int r_vm_mmu_real(struct r_vm_t *vm, int set);
|
||||
R_API int r_vm_mmu_cache_write(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);
|
||||
R_API int r_vm_mmu_read(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);
|
||||
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
|
||||
|
|
|
@ -65,7 +65,7 @@ R_API int r_str_word_set0(char *str)
|
|||
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;
|
||||
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)
|
||||
{
|
||||
char *text = (char *)string;
|
||||
char *tmp = (char *)string;
|
||||
int word = 0;
|
||||
char *text, *tmp;
|
||||
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(;*text && !isseparator(*text);text = text +1);
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
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
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
#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);
|
||||
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;
|
||||
}
|
||||
|
||||
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 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;
|
||||
}
|
||||
|
||||
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))
|
||||
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)
|
||||
return r_vm_mmu_cache_write(vm, off, data, len);
|
||||
fprintf(stderr, "vm_mmu_write!\n");
|
||||
// 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)
|
||||
|
|
19
libr/vm/op.c
19
libr/vm/op.c
|
@ -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)
|
||||
{
|
||||
char *p,*s;
|
||||
int j,k,len = strlen(str)+256;
|
||||
struct list_head *pos;
|
||||
char *p, *s, *arg0;
|
||||
int j, k, len = strlen(str)+256;
|
||||
int nargs = 0;
|
||||
char *arg0;
|
||||
|
||||
// eprintf("vmopeval(%s)\n", str);
|
||||
p = alloca(len);
|
||||
s = alloca(len);
|
||||
memcpy(p, str, len);
|
||||
memcpy(s, str, len);
|
||||
|
||||
struct list_head *pos;
|
||||
nargs = set0word(s);
|
||||
arg0 = get0word(s,0);
|
||||
nargs = r_str_word_set0(s);
|
||||
arg0 = r_str_word_get0(s, 0);
|
||||
|
||||
list_for_each(pos, &vm->ops) {
|
||||
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
|
||||
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) {
|
||||
strcpy(p+k, w);
|
||||
k += strlen(w)-1;
|
||||
|
@ -79,8 +77,7 @@ int r_vm_op_eval(struct r_vm_t *vm, const char *str)
|
|||
p[k]='\0';
|
||||
}
|
||||
}
|
||||
|
||||
return vm_eval(p);
|
||||
return r_vm_eval(vm, p);
|
||||
}
|
||||
|
||||
/* 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';
|
||||
eprintf("vm: opcode '%s' added\n", cmd);
|
||||
r_vm_op_add(vm, cmd, ptr+1);
|
||||
} else vm_cmd_op_help();
|
||||
} else r_vm_cmd_op_help();
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -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));
|
||||
} else {
|
||||
/* 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));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,18 +7,18 @@ void r_vm_stack_push(struct r_vm_t *vm, ut64 _val)
|
|||
{
|
||||
// XXX determine size of stack here
|
||||
// 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;
|
||||
vm_reg_set(vm, vm_cpu.sp, vm_reg_get(vm, vm_cpu.sp)+4);
|
||||
vm_mmu_write(vm, vm_reg_get(vm, vm_cpu.sp), &val, 4);
|
||||
r_vm_reg_set(vm, vm->cpu.sp, r_vm_reg_get(vm, vm->cpu.sp)+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)
|
||||
{
|
||||
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;
|
||||
//printf("POP (%s)\n", reg);
|
||||
vm_mmu_read(vm, vm_reg_get(vm, vm->cpu.sp), &val, 4);
|
||||
vm_reg_set(vm, reg, val);
|
||||
vm_reg_set(vm_cpu.sp, vm_reg_get(vm, vm->cpu.sp)-4);
|
||||
r_vm_mmu_read(vm, r_vm_reg_get(vm, vm->cpu.sp), (void *)&val, 4);
|
||||
r_vm_reg_set(vm, reg, val);
|
||||
r_vm_reg_set(vm, vm->cpu.sp, r_vm_reg_get(vm, vm->cpu.sp)-4);
|
||||
}
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
OBJ=test.o
|
||||
BIN=test
|
||||
BINDEPS=r_vm
|
||||
|
||||
include ../../rules.mk
|
|
@ -0,0 +1,9 @@
|
|||
#include <r_vm.h>
|
||||
|
||||
int main()
|
||||
{
|
||||
struct r_vm_t vm;
|
||||
r_vm_init(&vm, 1);
|
||||
/* ... TODO ... */
|
||||
return 0;
|
||||
}
|
15
libr/vm/vm.c
15
libr/vm/vm.c
|
@ -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)
|
||||
{
|
||||
/* 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);
|
||||
// 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->ops);
|
||||
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"));
|
||||
|
@ -247,8 +248,10 @@ R_API int r_vm_init(struct r_vm_t *vm, int init)
|
|||
//vm_setup_copy("esi", "edi");
|
||||
r_vm_setup_ret(vm, "eax");
|
||||
// TODO: do the same for fpregs and mmregs
|
||||
#if 0
|
||||
if (init) // XXX
|
||||
r_vm_arch_x86_init(vm);
|
||||
#endif
|
||||
break;
|
||||
#if 0
|
||||
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 {
|
||||
r_vm_mmu_read(vm, off, (ut8*)&_int32, 4);
|
||||
//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 {
|
||||
// [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))
|
||||
|| (!memcmp(ptr, "jmp ", 4))){
|
||||
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);
|
||||
r_vm_reg_set(vm, vm->cpu.pc, r_vm_get_value(vm, ptr+4));
|
||||
} else
|
||||
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));
|
||||
} else
|
||||
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));
|
||||
} else
|
||||
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
|
||||
if (!memcmp(str, "pop ", 4)) {
|
||||
r_vm_stack_pop(vm, str+5);
|
||||
|
|
Loading…
Reference in New Issue