mirror of
https://github.com/radareorg/radare2.git
synced 2025-02-01 02:53:22 +00:00
* 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:
parent
9efe88a9ce
commit
4ea6ee9873
7
TODO
7
TODO
@ -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
|
||||
|
@ -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
35
doc/brainfuck
Normal 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
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -96,4 +96,3 @@ R_API int r_core_patch (RCore *core, const char *patch) {
|
||||
fclose (fd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -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
21
libr/debug/p/bf.mk
Normal 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
522
libr/debug/p/bfvm.c
Normal 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
37
libr/debug/p/bfvm.h
Normal 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
107
libr/debug/p/debug_bf.c
Normal 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
|
@ -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){
|
||||
|
@ -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 };
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
@ -51,6 +51,7 @@ crypto.aes
|
||||
debug.native
|
||||
debug.gdb
|
||||
debug.rap
|
||||
debug.bf
|
||||
fs.fat
|
||||
fs.ntfs
|
||||
fs.ext2
|
||||
|
Loading…
x
Reference in New Issue
Block a user