* Implemented assembler support for asm.bf plugin

* Added support for breakpoints in the brainfuck debugger
  - Fixed write delegate in io.bfdbg plugin
  - asm.bf is now compiled as static in core
This commit is contained in:
pancake 2011-10-09 04:41:53 +02:00
parent a43068bde0
commit 13d24051b7
6 changed files with 94 additions and 29 deletions

View File

@ -2,27 +2,21 @@ Brainfuck support for r2
========================
Plugins for brainfuck:
- asm.bf - brainfuck disassembler
- debug.bf - debugger
- asm.bf - brainfuck assembler and disassembler
- debug.bf - debugger using bfvm
- anal.bf - code analysis for brainfuck
- bp.bf - breakpoints support (experimental)
To debug your brainfuck program type:
e asm.arch=bf
e cfg.debug=true
dh bf
To debug a brainfuck program:
You can also call this from the shell:
$ r2 -e asm.arch=bf -c "e cfg.debug=1;dh bf" /tmp/bf
$ r2 -e asm.arch=bf -D helloworld.bf
$ r2 -D bf bfdbg:///tmp/bf
The debugger creates virtual sections for code, data, screen and input.
TODO
----
- add support for comments, ignore invalid instructions as nops
- implement brainfuck assembler
- anal.bf - code analysis
- enhace io and debugger plugins to generate sections and set arch opts
Hello World
===========

View File

@ -22,10 +22,10 @@ static int disassemble(struct r_asm_t *a, struct r_asm_op_t *op, const ut8 *buf,
switch (*buf) {
case '[':
strcpy (op->buf_asm, "[ loop {");
strcpy (op->buf_asm, "[ do");
break;
case ']':
strcpy (op->buf_asm, "] }"); // TODO: detect clause and put label name
strcpy (op->buf_asm, "] loop"); // TODO: detect clause and put label name
break;
case '>':
if (i>1) strcpy (op->buf_asm, "> add ptr");
@ -64,15 +64,64 @@ static int disassemble(struct r_asm_t *a, struct r_asm_op_t *op, const ut8 *buf,
return i;
}
static int assemble(RAsm *a, RAsmOp *op, const char *buf) {
const char *arg = strchr (buf, ',');
const char *ref = strchr (buf, '[');
int n = 0;
if (!strncmp (buf, "nop", 3)) {
op->buf[0] = 0x90;
n++;
} else
if (!strncmp (buf, "inc", 3)) {
char ch = ref? '+': '>';
op->buf[0] = ch;
n = 1;
} else
if (!strncmp (buf, "dec", 3)) {
char ch = ref? '-': '<';
op->buf[0] = ch;
n = 1;
} else
if (!strncmp (buf, "sub", 3)) {
char ch = ref? '-': '<';
if (arg) {
n = atoi (arg+1);
memset (op->buf, ch, n);
} else {
op->buf[0] = '<';
n = 1;
}
} else
if (!strncmp (buf, "add", 3)) {
char ch = ref? '+': '>';
if (arg) {
n = atoi (arg+1);
memset (op->buf, ch, n);
} else {
op->buf[0] = '<';
n = 1;
}
} else
if (!strncmp (buf, "do", 2)) {
op->buf[0] = '[';
n = 1;
} else
if (!strncmp (buf, "loop", 4)) {
op->buf[0] = ']';
n = 1;
}
return n;
}
RAsmPlugin r_asm_plugin_bf = {
.name = "bf",
.arch = "bf",
.bits = 32, //(int[]){ 8, 16, 32, 0 }, // dummy
.bits = (int[]){32,0},
.desc = "Brainfuck disassembly plugin",
.init = NULL,
.fini = NULL,
.disassemble = &disassemble,
.assemble = NULL
.assemble = &assemble
};
#ifndef CORELIB

View File

@ -32,6 +32,7 @@ static ut8 bfvm_op(BfvmCPU *c) {
int bfvm_in_trap(BfvmCPU *c) {
switch (bfvm_op (c)) {
case 0x00:
case 0xcc:
case 0xff:
return 1;
}

View File

@ -36,11 +36,10 @@ static int is_io_bf(RDebug *dbg) {
static int r_debug_bf_step_over(RDebug *dbg) {
RIOBfdbg *o = dbg->iob.io->fd->data;
int op, oop = 0;
while (1) {
for (;;) {
op = bfvm_op (o->bfvm);
if (oop != 0 && op != oop)
break;
eprintf ("STEP OVER %d %d\n", o->bfvm->eip, op);
if (bfvm_in_trap (o->bfvm))
break;
bfvm_step (o->bfvm, 0);
@ -93,9 +92,7 @@ static int r_debug_bf_reg_write(RDebug *dbg, int type, const ut8 *buf, int size)
o->bfvm->input_idx = r.inpi;
o->bfvm->base = r.mem;
o->bfvm->ptr = r.memi; // dup
// TODO: do the rest
// TODO: set vm regs from internal struct
return R_FALSE; // XXX Error check
return R_TRUE;
}
static int r_debug_bf_continue(RDebug *dbg, int pid, int tid, int sig) {
@ -189,7 +186,7 @@ struct r_debug_plugin_t r_debug_plugin_bf = {
.reg_read = &r_debug_bf_reg_read,
.reg_write = &r_debug_bf_reg_write,
.reg_profile = (void *)r_debug_bf_reg_profile,
.breakpoint = r_debug_native_bp,
// .breakpoint = r_debug_native_bp,
//.ptr_write = &r_debug_bf_ptr_write,
//.ptr_read = &r_debug_bf_ptr_read,
};

View File

@ -33,16 +33,40 @@ static inline int is_in_base(ut64 off, BfvmCPU *c) {
static int __write(RIO *io, RIODesc *fd, const ut8 *buf, int count) {
RIOBfdbg *riom;
int sz;
if (fd == NULL || fd->data == NULL)
return -1;
riom = fd->data;
if (is_in_screen (io->off, riom->bfvm)) {
memcpy (RIOBFDBG_BUF (fd)+io->off, buf, count);
/* data base buffer */
if (is_in_base (io->off, riom->bfvm)) {
int n = io->off-riom->bfvm->base;
if (n>count)
count = n;
memcpy (riom->bfvm->mem+n, buf, count);
return count;
}
if (io->off+count >= RIOBFDBG_SZ (fd))
/* screen buffer */
if (is_in_screen (io->off, riom->bfvm)) {
int n = io->off-riom->bfvm->screen;
if (n>count)
count = riom->bfvm->screen_size-n;
memcpy (riom->bfvm->screen_buf+n, buf, count);
return count;
}
/* input buffer */
if (is_in_input (io->off, riom->bfvm)) {
int n = io->off-riom->bfvm->input;
if (n>count)
count = riom->bfvm->input_size-n;
memcpy (riom->bfvm->input_buf+n, buf, count);
return count;
}
/* read from file */
sz = RIOBFDBG_SZ (fd);
if (io->off+count >= sz)
count = sz-io->off;
if (io->off >= sz)
return -1;
//eprintf ("WRITE %d\n", count);
memcpy (RIOBFDBG_BUF (fd)+io->off, buf, count);
return count;
}
@ -114,7 +138,7 @@ static int __plugin_open(RIO *io, const char *pathname) {
}
static inline int getmalfd (RIOBfdbg *mal) {
return 0xfffffff & (int)(size_t)mal->buf;
return 0xffff & (int)(size_t)mal->buf;
}
static RIODesc *__open(RIO *io, const char *pathname, int rw, int mode) {

View File

@ -4,6 +4,7 @@
# fs.hfs
# fs.jfs
STATIC="asm.java
asm.bf
asm.arm
asm.armthumb
asm.sh
@ -88,7 +89,6 @@ parse.mreplace
parse.att2intel
parse.x86_pseudo"
SHARED="
asm.bf
asm.csr
asm.psosvm
io.shm"