mirror of
https://github.com/radareorg/radare2.git
synced 2024-11-27 15:10:53 +00:00
* 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:
parent
a43068bde0
commit
13d24051b7
@ -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
|
||||
===========
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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,
|
||||
};
|
||||
|
@ -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) {
|
||||
|
@ -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"
|
||||
|
Loading…
Reference in New Issue
Block a user