* Add new flags to r2

- -D : enable debugger mode for non native debuggers
  - -c cmd : execute a command before showing prompt
* Initial import of the bfvm (brainfuck virtual machine)
* Initial dummy implementation of the brainfuck debugger plugin
  - Needs to be integrated with bfvm to work
* Added doc/brainfuck
This commit is contained in:
pancake 2011-10-07 03:10:44 +02:00
parent 9efe88a9ce
commit 4ea6ee9873
15 changed files with 807 additions and 48 deletions

7
TODO
View File

@ -7,17 +7,15 @@
====[[ 0.8.6 ]]====
* implement 'ax' to get/set xrefs (better than afl <addr>)
* add 'pdb' command, print disassembled basic block (like pdf, but for bb)
* shell encoder - get x86-64 one from twitter
- http://funoverip.net/2011/09/simple-shellcode-obfuscation/
* enhace r_egg.. not usable til 0.9
* cleanup magic database.. too slow for search :(
* rabin2 -z /dev/sda1 TAKES TOO LONG. opening r2 /tmp/fs is SLOW as shit.
====[[ 0.9 ]]====
* Add support for classes (useful for c++, dex, objc, ...)
- command to add new classes
* Implement hex:// io :D like malloc but initialized.. use malloc here?
OSX
@ -44,7 +42,6 @@ Other stuff
* Dupped javasm bin/asm -- must merge
* Implement differential distance signature search
* Rename r_hashtable -> r_ht
- Make ht64.c include ht.c
* Add 'S' subcommand to display section size and get by perms rwx

View File

@ -15,9 +15,10 @@ static int threaded = 0;
static struct r_core_t r;
static int main_help(int line) {
printf ("Usage: radare2 [-dwnLqv] [-P patch] [-p prj] [-s addr] [-b bsz] [-e k=v] [file]\n");
printf ("Usage: radare2 [-dDwnLqv] [-P patch] [-p prj] [-s addr] [-b bsz] [-c cmd] [-e k=v] [file]\n");
if (!line) printf (
" -d use 'file' as a program to debug\n"
" -D enable debug mode (e cfg.debug=true)\n"
" -w open file in write mode\n"
" -n do not run ~/.radare2rc\n"
" -q quite mode (no prompt)\n"
@ -34,6 +35,7 @@ static int main_help(int line) {
#endif
" -L list supported IO plugins\n"
" -e k=v evaluate config var\n"
" -c \"cmd..\" execute radare command\n"
"Environment:\n"
" R_DEBUG if defined, show error messages and crash signal\n"
" LIBR_PLUGINS path to plugins directory\n"
@ -49,10 +51,9 @@ static int main_version() {
static int list_io_plugins(RIO *io) {
struct list_head *pos;
printf ("IO plugins:\n");
list_for_each_prev(pos, &io->io_list) {
struct r_io_list_t *il = list_entry(pos, struct r_io_list_t, list);
printf(" %-10s %s\n", il->plugin->name, il->plugin->desc);
printf (" %-10s %s\n", il->plugin->name, il->plugin->desc);
}
return 0;
}
@ -87,6 +88,8 @@ int main(int argc, char **argv) {
RThreadLock *lock = NULL;
RThread *rabin_th = NULL;
#endif
RListIter *iter;
char *cmdn;
RCoreFile *fh = NULL;
const char *patchfile = NULL;
//int threaded = R_FALSE;
@ -100,6 +103,7 @@ int main(int argc, char **argv) {
char file[4096];
char *cmdfile = NULL;
int is_gdb = R_FALSE;
RList *cmds = r_list_new ();
if (r_sys_getenv ("R_DEBUG"))
r_sys_crash_handler ("gdb --pid %d");
@ -108,7 +112,7 @@ int main(int argc, char **argv) {
return main_help (1);
r_core_init (&r);
while ((c = getopt (argc, argv, "wfhe:ndqvs:p:b:Lui:l:P:"
while ((c = getopt (argc, argv, "wfhe:ndqvs:p:b:Lui:l:P:c:D"
#if USE_THREADS
"t"
#endif
@ -119,6 +123,9 @@ int main(int argc, char **argv) {
threaded = R_TRUE;
break;
#endif
case 'D':
debug = 2;
break;
case 'q':
r_config_set (r.config, "scr.prompt", "false");
break;
@ -128,6 +135,9 @@ int main(int argc, char **argv) {
case 'P':
patchfile = optarg;
break;
case 'c':
r_list_append (cmds, optarg);
break;
case 'i':
cmdfile = optarg;
break;
@ -175,45 +185,54 @@ int main(int argc, char **argv) {
eprintf ("No program given to -d\n");
return 1;
}
is_gdb = (!memcmp (argv[optind], "gdb://", 6));
if (is_gdb) *file = 0;
else memcpy (file, "dbg://", 7);
if (optind < argc) {
char *ptr = r_file_path (argv[optind]);
if (ptr) {
strcat (file, ptr);
free (ptr);
optind++;
if (debug == 2) {
// autodetect backend with -D
if (!strcmp (r_config_get (r.config, "asm.arch"), "bf")) {
r_config_set (r.config, "dbg.backend", "bf");
}
}
while (optind < argc) {
int largv = strlen (argv[optind]);
if (filelen+largv+1>=sizeof (file)) {
eprintf ("Too long arguments\n");
return 1;
} else {
is_gdb = (!memcmp (argv[optind], "gdb://", 6));
if (is_gdb) *file = 0;
else memcpy (file, "dbg://", 7);
if (optind < argc) {
char *ptr = r_file_path (argv[optind]);
if (ptr) {
strcat (file, ptr);
free (ptr);
optind++;
}
}
memcpy (file+filelen, argv[optind], largv);
filelen += largv;
if (filelen+6>=sizeof (file)) {
eprintf ("Too long arguments\n");
return 1;
}
memcpy (file+filelen, " ", 2);
filelen += 2;
if (++optind != argc) {
while (optind < argc) {
int largv = strlen (argv[optind]);
if (filelen+largv+1>=sizeof (file)) {
eprintf ("Too long arguments\n");
return 1;
}
memcpy (file+filelen, argv[optind], largv);
filelen += largv;
if (filelen+6>=sizeof (file)) {
eprintf ("Too long arguments\n");
return 1;
}
memcpy (file+filelen, " ", 2);
filelen += 2;
if (++optind != argc) {
memcpy (file+filelen, " ", 2);
filelen += 2;
}
}
fh = r_core_file_open (&r, file, perms, 0LL);
if (fh != NULL) {
//const char *arch = r_config_get (r.config, "asm.arch");
// TODO: move into if (debug) ..
if (is_gdb) r_debug_use (r.dbg, "gdb");
else r_debug_use (r.dbg, "native");
}
}
}
fh = r_core_file_open (&r, file, perms, 0LL);
if (fh != NULL) {
//const char *arch = r_config_get (r.config, "asm.arch");
// TODO: move into if (debug) ..
if (is_gdb) r_debug_use (r.dbg, "gdb");
else r_debug_use (r.dbg, "native");
}
} else {
if (!debug || debug==2) {
if (optind<argc) {
while (optind < argc)
fh = r_core_file_open (&r, argv[optind++], perms, 0);
@ -227,6 +246,12 @@ int main(int argc, char **argv) {
}
}
/* execute -c commands */
r_list_foreach (cmds, iter, cmdn) {
r_core_cmd0 (&r, cmdn);
}
r_list_free (cmds);
if (fh == NULL) {
if (perms & R_IO_WRITE)
eprintf ("Cannot open file for writing.\n");

35
doc/brainfuck Normal file
View File

@ -0,0 +1,35 @@
Brainfuck support for r2
========================
Plugins for brainfuck:
- asm.bf - brainfuck disassembler
- debug.bf - debugger
To debug your brainfuck program type:
e asm.arch=bf
e cfg.debug=true
dh bf
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
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
Hello World
===========
>+++++++++[<++++++++>-]<.>+++++++[<++++>-]<+.+++++++..+++.[-]
>++++++++[<++++>-] <.>+++++++++++[<++++++++>-]<-.--------.+++
.------.--------.[-]>++++++++[<++++>- ]<+.[-]++++++++++.
$ cat << EOF
>+++++++++[<++++++++>-]<.>+++++++[<++++>-]<+.+++++++..+++.[-]>++++++++[<++++>-] <.>+++++++++++[<++++++++>-]<-.--------.+++.------.--------.[-]>++++++++[<++++>- ]<+.[-]++++++++++.
EOF

View File

@ -128,8 +128,9 @@ static int config_asmos_callback(void *user, void *data) {
if (!r_syscall_setup (core->anal->syscall,
r_config_get (core->config, "asm.arch"),
node->value,
core->anal->bits))
core->anal->bits)) {
eprintf ("asm.os: Cannot setup syscall os/arch for '%s'\n", node->value);
}
return R_TRUE;
}
@ -323,6 +324,8 @@ static int config_asmarch_callback(void *user, void *data) {
r_config_get (core->config, "asm.os"),
core->anal->bits))
eprintf ("asm.arch: Cannot setup syscall os/arch for '%s'\n", node->value);
if (!strcmp (node->value, "bf"))
r_config_set (core->config, "dbg.backend", "bf");
return R_TRUE;
}

View File

@ -96,4 +96,3 @@ R_API int r_core_patch (RCore *core, const char *patch) {
fclose (fd);
return 0;
}

View File

@ -1,5 +1,5 @@
NAME=r_debug
DEPS=r_reg r_anal r_bp r_util r_io r_parse
DEPS=r_reg r_anal r_bp r_util r_io r_parse r_cons
CFLAGS+=-DCORELIB
foo: pre libs tests plugins

21
libr/debug/p/bf.mk Normal file
View File

@ -0,0 +1,21 @@
CFLAGS+=-Ip/libbfwbf/include
ifeq (${OSTYPE},windows)
LDFLAGS+=-lwsock32
endif
ifeq (${OSTYPE},solaris)
LDFLAGS+=-lsocket
endif
OBJ_BF=debug_bf.o
#libbfwbf/bfwbfper.o
#libbfwbf/bfwbfper.o:
# ${CC} -c ${CFLAGS} ${LDFLAGS} -o p/libbfwbf/bfwbfper.o p/libbfwbf/bfwbfper.c
STATIC_OBJ+=${OBJ_BF}
TARGET_BF=debug_bf.${EXT_SO}
ALL_TARGETS+=${TARGET_BF}
${TARGET_BF}: ${OBJ_BF}
${CC} $(call libname,debug_bf) ${OBJ_BF} ${CFLAGS} ${LDFLAGS} -o ${TARGET_BF}

522
libr/debug/p/bfvm.c Normal file
View File

@ -0,0 +1,522 @@
/*
* Copyright (C) 2008-2011 -- pancake <@nopcode.org>
*
* NOTE: This file has been ported from r1
*
* radare is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* radare is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with radare; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
*/
#include "bfvm.h"
ut8 bfvm_op(BfvmCPU *c) {
ut8 buf[4];
if (!c->iob.read_at (c->iob.io, c->eip, buf, 4))
return 0xff;
return buf[0];
}
int bfvm_in_trap(BfvmCPU *c) {
switch (bfvm_op (c)) {
case 0x00:
case 0xff:
return 1;
}
return 0;
}
int bfvm_init(BfvmCPU *c, ut32 size, int circular) {
memset (c, '\0', sizeof (BfvmCPU));
/* data */
c->mem = (ut8 *)malloc (size);
if (c->mem == NULL)
return 0;
c->base = BFVM_DATA_ADDR;
memset (c->mem,'\0',size);
/* setup */
c->circular = circular;
c->eip = 0; // look forward nops
c->size = size;
/* screen */
c->screen = BFVM_SCREEN_ADDR;
c->screen_size = BFVM_SCREEN_SIZE;
c->screen_buf = (ut8*)malloc (c->screen_size);
memset (c->screen_buf, '\0', c->screen_size);
/* input */
c->input = BFVM_INPUT_ADDR;
c->input_size = BFVM_INPUT_SIZE;
c->input_buf = (ut8*)malloc (c->input_size);
memset (c->input_buf, '\0', c->input_size);
c->esp = c->base;
return 1;
}
R_API BfvmCPU *bfvm_new(RIOBind *iob) {
BfvmCPU *c = R_NEW0 (BfvmCPU);
bfvm_init (c, 4096, 0);
memcpy (&c->iob, iob, sizeof (c->iob));
return c;
}
BfvmCPU *bfvm_destroy(BfvmCPU *c) {
free (c->mem);
c->mem = 0;
free (c->screen_buf);
c->screen_buf = 0;
free (c);
return NULL;
}
ut8 *bfvm_get_ptr_at(BfvmCPU *c, ut64 at) {
if (at >= c->base)
at-=c->base;
if (at<0) {
if (c->circular)
at = c->size-2;
else at=0;
} else
if (at >= c->size) {
if (c->circular)
at = 0;
else at = c->size-1;
}
if (at<0) return c->mem;
return c->mem+at;
}
ut8 *bfvm_get_ptr(BfvmCPU *c) {
//return bfvm_cpu.mem;
return bfvm_get_ptr_at (c, c->ptr);
}
ut8 bfvm_get(BfvmCPU *c) {
ut8 *ptr = bfvm_get_ptr (c);
if (ptr != NULL)
return ptr[0];
return 0;
}
void bfvm_inc(BfvmCPU *c) {
ut8 *mem = bfvm_get_ptr (c);
if (mem != NULL)
*mem++;
}
void bfvm_dec(BfvmCPU *c) {
ut8 *mem = bfvm_get_ptr (c);
if (mem != NULL)
*mem--;
}
int bfvm_reg_set(BfvmCPU *c, const char *str) {
char *ptr = strchr (str, ' ');
if (ptr == NULL)
return 0;
if (strstr (str, "eip"))
c->eip = r_num_math (NULL, ptr+1);
else if (strstr (str, "esp"))
c->esp = r_num_math (NULL, ptr+1);
else if (strstr (str, "ptr"))
c->ptr = r_num_math (NULL, ptr+1);
return 1;
}
/* screen and input */
void bfvm_peek(BfvmCPU *c) {
int idx = c->input_idx;
ut8 *ptr = bfvm_get_ptr (c);
if (idx >= c->input_size)
idx = 0;
if (ptr) {
*ptr = c->input_buf[idx];
c->input_idx = idx+1;
}
}
void bfvm_poke(BfvmCPU *c) {
int idx = c->screen_idx;
c->screen_buf[idx] = bfvm_get (c);
c->screen_idx = idx+1;
}
int bfvm_trace_op(BfvmCPU *c, ut8 op) {
ut8 g;
switch (op) {
case '\0':
eprintf (" ; trap (%02x)\n", op);
case '.':
case ',':
case '+':
case '-':
case '>':
case '<':
eprintf ("%c", op);
break;
case '[':
case ']':
g = bfvm_get (c);
eprintf ("%c ; [ptr] = %d\n", op, g);
if (g!= 0)
eprintf ("[");
break;
}
return 0;
}
#define T if (c->trace)
/* debug */
int bfvm_step(BfvmCPU *c, int over) {
ut8 *buf;
ut8 op = bfvm_op (c);
ut8 op2;
do {
T bfvm_trace_op(c, op);
switch(op) {
case '\0':
/* trap */
return 1;
case '.':
buf = bfvm_get_ptr (c);
bfvm_poke (c);
break;
case ',':
bfvm_peek (c);
/* TODO read */
break;
case '+':
bfvm_inc (c);
break;
case '-':
bfvm_dec (c);
break;
case '>':
c->ptr++;
break;
case '<':
c->ptr--;
break;
case '[':
break;
case ']':
if (bfvm_get (c) != 0) {
do {
c->eip--;
/* control underflow */
if (c->eip<0) {
c->eip = 0;
break;
}
} while (bfvm_op (c)!='[');
}
break;
default:
break;
}
c->eip++;
op2 = bfvm_op (c);
} while (over && op == op2);
return 0;
}
int bfvm_contsc(BfvmCPU *c) {
RCons *ci = r_cons_singleton ();
r_cons_break (NULL, 0);
while (!ci->breaked) {
bfvm_step (c, 0);
if (bfvm_in_trap (c)) {
eprintf("Trap instruction at 0x%08llx\n", c->eip);
break;
}
switch (bfvm_op (c)) {
case ',':
eprintf("contsc: read from input trap\n");
ci->breaked = 1;
continue;
case '.':
eprintf ("contsc: print to screen trap\n");
ci->breaked = 1;
continue;
}
}
r_cons_break_end ();
return 0;
}
int bfvm_cont(BfvmCPU *c, ut64 until) {
RCons *ci = r_cons_singleton ();
r_cons_break (NULL, 0);
while (!ci->breaked && c->eip != until) {
bfvm_step (c, 0);
if (bfvm_in_trap (c)) {
eprintf ("Trap instruction at 0x%08llx\n", c->eip);
break;
}
}
r_cons_break_end ();
return 0;
}
int bfvm_trace(BfvmCPU *c, ut64 until) {
c->trace=1;
bfvm_cont (c, until);
c->trace=0;
return 0;
}
void bfvm_show_regs(BfvmCPU *c, int rad) {
if (rad) {
eprintf ("fs regs\n");
eprintf ("f eip @ 0x%08llx\n", (ut64)c->eip);
eprintf ("f esp @ 0x%08llx\n", (ut64)c->esp);
eprintf ("f ptr @ 0x%08llx\n", (ut64)c->ptr+c->base);
eprintf ("fs *\n");
} else {
ut8 ch = bfvm_get (c);
eprintf (" eip 0x%08llx esp 0x%08llx\n",
(ut64)c->eip, (ut64)c->esp);
eprintf (" ptr 0x%08x [ptr] %d = 0x%02x '%c'\n",
(ut32)c->ptr, ch, ch, IS_PRINTABLE (ch)? ch:' ');
}
}
void bfvm_maps(BfvmCPU *c, int rad) {
if (rad) {
eprintf ("fs sections\n");
eprintf ("e cmd.vprompt=px@screen\n");
eprintf ("f section_code @ 0x%08llx\n", (ut64)BFVM_CODE_ADDR);
eprintf ("f section_code_end @ 0x%08llx\n", (ut64)BFVM_CODE_ADDR+BFVM_CODE_SIZE);
eprintf ("f section_data @ 0x%08llx\n", (ut64)c->base);
eprintf ("f section_data_end @ 0x%08llx\n", (ut64)c->base+c->size);
eprintf ("f screen @ 0x%08llx\n", (ut64)c->screen);
eprintf ("f section_screen @ 0x%08llx\n", (ut64)c->screen);
eprintf ("f section_screen_end @ 0x%08llx\n", (ut64)c->screen+c->screen_size);
eprintf ("f input @ 0x%08llx\n", (ut64)c->input);
eprintf ("f section_input @ 0x%08llx\n", (ut64)c->input);
eprintf ("f section_input_end @ 0x%08llx\n", (ut64)c->input+c->input_size);
eprintf ("fs *\n");
} else {
eprintf ("0x%08llx - 0x%08llx rwxu 0x%08llx .code\n",
(ut64)0, (ut64)c->size, (ut64)c->size);
eprintf ("0x%08llx - 0x%08llx rw-- 0x%08llx .data\n",
(ut64)c->base, (ut64)(c->base+c->size), (ut64)c->size);
eprintf ("0x%08llx - 0x%08llx rw-- 0x%08llx .screen\n",
(ut64)c->screen, (ut64)(c->screen+c->screen_size), (ut64)c->screen_size);
eprintf ("0x%08llx - 0x%08llx rw-- 0x%08llx .input\n",
(ut64)c->input, (ut64)(c->input+c->input_size), (ut64)c->input_size);
}
}
#if 0
/* PLUGIN CODE */
ut64 cur_seek = 0;
int bfdbg_fd = -1;
int bfdbg_handle_fd(int fd)
{
return fd == bfdbg_fd;
}
int bfdbg_handle_open(const char *file)
{
if (!memcmp(file, "bfdbg://", 8))
return 1;
return 0;
}
ssize_t bfdbg_write(int fd, const void *buf, size_t count)
{
if (cur_seek>=bfvm_cpu.screen && cur_seek<=bfvm_cpu.screen+bfvm_cpu.screen_size) {
memcpy(bfvm_cpu.screen_buf+cur_seek-bfvm_cpu.screen, buf, count);
return count;
}
if (cur_seek>=bfvm_cpu.input && cur_seek<=bfvm_cpu.input+bfvm_cpu.input_size) {
memcpy(bfvm_cpu.input_buf+cur_seek-bfvm_cpu.input, buf, count);
return count;
}
if (cur_seek>=bfvm_cpu.base) {
memcpy(bfvm_cpu.mem+cur_seek-bfvm_cpu.base, buf, count);
return count;
}
// TODO: call real read/write here?!?
return write(fd, buf, count);
}
ssize_t bfdbg_read(int fd, void *buf, size_t count)
{
if (cur_seek>=bfvm_cpu.screen && cur_seek<=bfvm_cpu.screen+bfvm_cpu.screen_size) {
memcpy(buf, bfvm_cpu.screen_buf, count);
return count;
}
if (cur_seek>=bfvm_cpu.input && cur_seek<=bfvm_cpu.input+bfvm_cpu.input_size) {
memcpy(buf, bfvm_cpu.input_buf, count);
return count;
}
if (cur_seek>=bfvm_cpu.base) {
memcpy(buf, bfvm_cpu.mem, count);
return count;
}
return read(fd, buf, count);
}
int bfdbg_open(const char *pathname, int flags, mode_t mode)
{
int fd = -1;
if (bfdbg_handle_open(pathname)) {
fd = open(pathname+8, flags, mode);
if (fd != -1) {
bfvm_init(0xFFFF, 1);
bfdbg_fd = fd;
}
}
return fd;
}
int bfdbg_system(const char *cmd)
{
if (!memcmp(cmd, "info",4)) {
bfvm_step(0);
} else
if (!memcmp(cmd, "help",4)) {
eprintf("Brainfuck debugger help:\n");
eprintf("20!step ; perform 20 steps\n");
eprintf("!step ; perform a step\n");
eprintf("!stepo ; step over rep instructions\n");
eprintf("!maps ; show registers\n");
eprintf("!reg ; show registers\n");
eprintf("!cont [addr] ; continue until address or ^C\n");
eprintf("!trace [addr] ; trace code execution\n");
eprintf("!contsc ; continue until write or read syscall\n");
eprintf("!reg eip 3 ; force program counter\n");
eprintf(".!reg* ; adquire register information into core\n");
} else
if (!memcmp(cmd, "contsc",6)) {
bfvm_contsc();
} else
if (!memcmp(cmd, "cont",4)) {
bfvm_cont(get_math(cmd+4));
} else
if (!memcmp(cmd, "trace",5)) {
bfvm_trace(get_math(cmd+5));
} else
if (!memcmp(cmd, "stepo",5)) {
bfvm_step(1);
} else
if (!memcmp(cmd, "maps",4)) {
bfvm_maps(cmd[4]=='*');
} else
if (!memcmp(cmd, "step",4)) {
bfvm_step(0);
} else
if (!memcmp(cmd, "reg",3)) {
if (strchr(cmd+4,' ')) {
bfvm_reg_set(cmd+4);
} else {
switch (cmd[3]) {
case 's':
switch(cmd[4]) {
case '*':
bfvm_show_regs(1);
break;
default:
bfvm_show_regs(0);
break;
}
break;
case '*':
bfvm_show_regs(1);
break;
default:
//case ' ':
//case '\0':
bfvm_show_regs(0);
break;
}
}
} else eprintf("Invalid debugger command. Try !help\n");
return 0;
}
int bfdbg_close(int fd)
{
if (fd == bfdbg_fd)
bfvm_destroy(&bfvm_cpu);
return close(fd);
}
ut64 bfdbg_lseek(int fildes, ut64 offset, int whence)
{
switch(whence) {
case SEEK_SET:
cur_seek = offset;
break;
case SEEK_CUR:
cur_seek = config.seek+offset;
break;
#if 1
case SEEK_END:
//if (cur_seek>bfvm_cpu.base)
cur_seek = 0xffffffff;
return cur_seek;
#endif
}
#if __WINDOWS__
return _lseek(fildes,(long)offset,whence);
#else
#if __linux__
return lseek64(fildes,(off_t)offset,whence);
#else
return lseek(fildes,(off_t)offset,whence);
#endif
#endif
}
int bfdbg_plugin_init() {
return bfvm_init(0xFFFF, 1);
}
#if 0
struct debug_t bfdbgt = {
/* TODO */
};
#endif
plugin_t bfdbg_plugin = {
.name = "bfdbg",
.desc = "brainfuck debugger",
.init = bfdbg_plugin_init,
.debug = NULL, //&bfdbgt,
.system = bfdbg_system,
.widget = NULL,
.handle_fd = bfdbg_handle_fd,
.handle_open = bfdbg_handle_open,
.open = bfdbg_open,
.read = bfdbg_read,
.write = bfdbg_write,
.lseek = bfdbg_lseek,
.close = bfdbg_close
};
#endif

37
libr/debug/p/bfvm.h Normal file
View File

@ -0,0 +1,37 @@
#ifndef _R_BFVM_INCLUDE_
#define _R_BFVM_INCLUDE_
#include <r_io.h>
#include <r_util.h>
#include <r_cons.h>
#define BFVM_SCREEN_ADDR 0x50000
#define BFVM_SCREEN_SIZE 4096
#define BFVM_INPUT_ADDR 0x10000
#define BFVM_INPUT_SIZE 4096
#define BFVM_DATA_ADDR 0xd00000
#define BFVM_DATA_SIZE 4096
#define BFVM_CODE_ADDR 0
#define BFVM_CODE_SIZE 4096 /* XXX */
typedef struct bfvm_cpu_t {
ut64 eip;
ut64 esp;
int ptr;
int trace;
ut64 base;
ut8 *mem;
ut32 size;
ut64 screen;
int screen_idx;
int screen_size;
ut8 *screen_buf;
ut64 input;
int input_idx;
int input_size;
ut8 *input_buf;
int circular; /* circular memory */
RIOBind iob;
} BfvmCPU;
#endif

107
libr/debug/p/debug_bf.c Normal file
View File

@ -0,0 +1,107 @@
/* radare - LGPL - Copyright 2011 pancake<nopcode.org> */
#include <r_asm.h>
#include <r_debug.h>
struct bfvm_regs {
ut32 pc;
ut32 bp;
ut32 sp;
};
static struct bfvm_regs r;
static int r_debug_bf_step(RDebug *dbg) {
eprintf ("BF STEP\n");
r.pc++;
return R_TRUE;
}
static int r_debug_bf_reg_read(RDebug *dbg, int type, ut8 *buf, int size) {
memcpy (buf, &r, sizeof (r));
//r_io_system (dbg->iob.io, "dr");
return sizeof (r);
}
static int r_debug_bf_reg_write(int pid, int tid, int type, const ut8 *buf, int size) {
return R_FALSE; // XXX Error check
}
static int r_debug_bf_continue(RDebug *dbg, int pid, int tid, int sig) {
r_io_system (dbg->iob.io, "dc");
return R_TRUE;
}
static int r_debug_bf_wait(RDebug *dbg, int pid) {
/* do nothing */
return R_TRUE;
}
static int r_debug_bf_attach(RDebug *dbg, int pid) {
// XXX TODO PID must be a socket here !!1
RIODesc *d = dbg->iob.io->fd;
if (d && d->plugin && d->plugin->name) {
if (!strcmp ("bf", d->plugin->name)) {
eprintf ("SUCCESS: bf attach with inferior bf rio worked\n");
} else {
eprintf ("ERROR: Underlaying IO descriptor is not a GDB one..\n");
}
}
return R_TRUE;
}
static int r_debug_bf_detach(int pid) {
// XXX TODO PID must be a socket here !!1
// close (pid);
//XXX Maybe we should continue here?
return R_TRUE;
}
static char *r_debug_bf_reg_profile(RDebug *dbg) {
return strdup (
"=pc pc\n"
"=sp sp\n"
"=bp bp\n"
"gpr pc .32 0 0\n"
"gpr bp .32 4 0\n"
"gpr sp .32 8 0\n"
);
}
static int r_debug_bf_breakpoint (void *user, int type, ut64 addr, int hw, int rwx){
//r_io_system (dbg->iob.io, "db");
return R_FALSE;
}
struct r_debug_plugin_t r_debug_plugin_bf = {
.name = "bf",
/* TODO: Add support for more architectures here */
.arch = 0xff,
.bits = R_SYS_BITS_32,
.init = NULL,
.step = r_debug_bf_step,
.cont = r_debug_bf_continue,
.attach = &r_debug_bf_attach,
.detach = &r_debug_bf_detach,
.wait = &r_debug_bf_wait,
.pids = NULL,
.tids = NULL,
.threads = NULL,
.kill = NULL,
.frames = NULL,
.map_get = NULL,
.breakpoint = &r_debug_bf_breakpoint,
.reg_read = &r_debug_bf_reg_read,
.reg_write = &r_debug_bf_reg_write,
.reg_profile = (void *)r_debug_bf_reg_profile,
//.bp_write = &r_debug_bf_bp_write,
//.bp_read = &r_debug_bf_bp_read,
};
#ifndef CORELIB
struct r_lib_struct_t radare_plugin = {
.type = R_LIB_TYPE_DBG,
.data = &r_debug_plugin_bf
};
#endif

View File

@ -1,6 +1,7 @@
/* radare - LGPL - Copyright 2011 pancake<nopcode.org> */
#include <r_asm.h>
#include <r_cons.h>
#include <r_debug.h>
static int r_debug_rap_step(RDebug *dbg) {
@ -48,9 +49,14 @@ static int r_debug_rap_detach(int pid) {
return R_TRUE;
}
static const char *r_debug_rap_reg_profile(RDebug *dbg) {
static char *r_debug_rap_reg_profile(RDebug *dbg) {
char *out, *tf = r_file_temp ("/tmp/rap.XXXXXX");
int fd = r_cons_pipe_open (tf, 0);
r_io_system (dbg->iob.io, "drp");
return NULL;
r_cons_pipe_close (fd);
out = r_file_slurp (tf, NULL);
r_file_rm (tf);
return out;
}
static int r_debug_rap_breakpoint (void *user, int type, ut64 addr, int hw, int rwx){

View File

@ -7,6 +7,7 @@
extern RDebugPlugin r_debug_plugin_native;
extern RDebugPlugin r_debug_plugin_rap;
extern RDebugPlugin r_debug_plugin_gdb;
extern RDebugPlugin r_debug_plugin_bf;
static RDebugPlugin *debug_static_plugins[] =
{ R_DEBUG_STATIC_PLUGINS };

View File

@ -62,7 +62,7 @@ R_API int r_syscall_setup(RSyscall *ctx, const char *arch, const char *os, int b
snprintf (file, sizeof (file), PREFIX"/%s/%s-%s-%d.sdb",
SYSCALLPATH, os, arch, bits);
if (!r_file_exist (file)) {
eprintf ("r_syscall_setup: Cannot find '%s'\n", file);
//eprintf ("r_syscall_setup: Cannot find '%s'\n", file);
return R_FALSE;
}

View File

@ -9,7 +9,8 @@
.Op Fl s Ar addr
.Op Fl b Ar bsize
.Op Fl e Ar k=v
.Op Fl dwnLV
.Op Fl c Ar cmd
.Op Fl dDwnLV
.Ar file
.Sh DESCRIPTION
radare2 is a commandline hexadecimal editor.
@ -26,10 +27,14 @@ Start seeking at this address.
Set block size
.It Fl e Ar k=v
Set configuration eval variable key=value. For example -e scr.color=false
.It Fl c Ar cmd
Execute the given command before giving prompt
.It Fl f
Blocksize = file size.
.It Fl d
Start in debugger mode.
.It Fl D
Enable debug mode. Set cfg.debug=true
.It Fl w
Open in write mode.
.It Fl u

View File

@ -51,6 +51,7 @@ crypto.aes
debug.native
debug.gdb
debug.rap
debug.bf
fs.fat
fs.ntfs
fs.ext2