2010-01-26 00:28:33 +00:00
|
|
|
/* radare - LGPL - Copyright 2009-2010 pancake<nopcode.org> */
|
2009-02-05 21:08:46 +00:00
|
|
|
|
2009-04-15 18:24:19 +00:00
|
|
|
#include <r_core.h>
|
2009-04-11 21:22:20 +00:00
|
|
|
#include "../config.h"
|
2009-02-05 21:08:46 +00:00
|
|
|
|
2010-05-19 22:59:42 +00:00
|
|
|
static ut64 num_callback(RNum *userptr, const char *str, int *ok) {
|
|
|
|
RCore *core = (RCore *)userptr; // XXX ?
|
2010-04-14 20:28:45 +00:00
|
|
|
RFlagItem *flag;
|
2010-05-20 23:46:26 +00:00
|
|
|
RAnalOp aop;
|
2010-06-16 19:44:19 +00:00
|
|
|
ut64 ret;
|
2009-02-05 21:08:46 +00:00
|
|
|
|
|
|
|
if (str[0]=='$') {
|
2009-04-15 18:24:19 +00:00
|
|
|
/* analyze opcode */
|
2010-02-02 10:09:52 +00:00
|
|
|
switch (str[1]) {
|
2010-01-30 13:02:53 +00:00
|
|
|
case '$':
|
2010-02-02 10:09:52 +00:00
|
|
|
return (str[2]=='$')? aop.length:core->offset;
|
2009-04-15 18:24:19 +00:00
|
|
|
case 'e':
|
|
|
|
case 'j':
|
|
|
|
case 'f':
|
|
|
|
case 'r':
|
2010-05-19 22:59:42 +00:00
|
|
|
r_anal_aop (core->anal, &aop, core->offset,
|
2010-02-22 03:02:13 +00:00
|
|
|
core->block, core->blocksize);
|
2009-04-15 18:24:19 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* return value */
|
2010-02-02 10:09:52 +00:00
|
|
|
switch (str[1]) {
|
2009-04-15 18:24:19 +00:00
|
|
|
case '{':
|
|
|
|
{
|
|
|
|
char *ptr, *bptr = strdup(str+2);
|
|
|
|
ptr = strchr(bptr, '}');
|
|
|
|
if (ptr != NULL) {
|
2009-07-08 11:49:55 +00:00
|
|
|
ut64 ret;
|
2009-04-15 18:24:19 +00:00
|
|
|
ptr[0]='\0';
|
2010-05-19 22:59:42 +00:00
|
|
|
ret = r_config_get_i (core->config, bptr);
|
2010-03-26 16:01:25 +00:00
|
|
|
free (bptr);
|
2009-04-15 18:24:19 +00:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
case 'e': return aop.eob;
|
|
|
|
case 'j': return aop.jump;
|
|
|
|
case 'f': return aop.fail;
|
|
|
|
case 'r': return aop.ref;
|
2009-02-05 21:08:46 +00:00
|
|
|
case 'b': return core->blocksize;
|
2009-04-15 00:29:01 +00:00
|
|
|
case 's': return core->file->size;
|
2010-05-19 22:59:42 +00:00
|
|
|
case '?': return core->num->value;
|
2009-02-05 21:08:46 +00:00
|
|
|
}
|
|
|
|
}
|
2010-06-16 19:44:19 +00:00
|
|
|
if ( (flag = r_flag_get (core->flags, str)) ) {
|
|
|
|
ret = flag->offset;
|
|
|
|
*ok = R_TRUE;
|
|
|
|
} else *ok = ret = 0;
|
|
|
|
return ret;
|
2009-02-05 21:08:46 +00:00
|
|
|
}
|
|
|
|
|
2010-03-19 03:02:23 +00:00
|
|
|
R_API RCore *r_core_new() {
|
|
|
|
RCore *c = R_NEW (struct r_core_t);
|
2010-01-30 13:02:53 +00:00
|
|
|
r_core_init (c);
|
2009-02-05 21:08:46 +00:00
|
|
|
return c;
|
|
|
|
}
|
|
|
|
|
2009-04-07 11:28:22 +00:00
|
|
|
/*-----------------------------------*/
|
|
|
|
#define CMDS 54
|
|
|
|
static const char *radare_argv[CMDS] ={
|
2010-01-30 13:02:53 +00:00
|
|
|
"?", "!step", "!stepo", "!cont", "!signal", "!fd", "!maps", ".!maps*",
|
|
|
|
"!bp", "!!", "#md5", "#sha1", "#crc32", "#entropy", "Visual", "ad", "ac",
|
|
|
|
"ag", "emenu", "eval", "seek", "info", "help", "move", "quit", "flag",
|
|
|
|
"Po", "Ps", "Pi", "H", "H no", "H nj", "H fj", "H lua", "x", "b",
|
|
|
|
"y", "yy", "y?", "wx", "ww", "wf", "w?", "pD", "pG", "pb", "px",
|
|
|
|
"pX", "po", "pm", "pz", "pr >", "p?", NULL
|
2009-04-07 11:28:22 +00:00
|
|
|
};
|
|
|
|
|
2010-02-28 21:58:21 +00:00
|
|
|
static int myfgets(char *buf, int len) {
|
2009-04-07 11:28:22 +00:00
|
|
|
/* TODO: link against dietline if possible for autocompletion */
|
|
|
|
char *ptr;
|
2010-02-18 15:36:55 +00:00
|
|
|
RLine *rli = r_line_singleton ();
|
2009-04-07 11:28:22 +00:00
|
|
|
buf[0]='\0';
|
2010-02-18 15:36:55 +00:00
|
|
|
rli->completion.argc = CMDS;
|
|
|
|
rli->completion.argv = radare_argv;
|
2010-01-30 13:02:53 +00:00
|
|
|
ptr = r_line_readline (); //CMDS, radare_argv);
|
2009-04-07 11:28:22 +00:00
|
|
|
if (ptr == NULL)
|
2010-03-04 11:43:16 +00:00
|
|
|
return -2;
|
2010-01-09 01:05:04 +00:00
|
|
|
strncpy (buf, ptr, len);
|
|
|
|
//free(ptr); // XXX leak
|
|
|
|
return strlen (buf)+1;
|
2009-04-07 11:28:22 +00:00
|
|
|
}
|
|
|
|
/*-----------------------------------*/
|
|
|
|
|
2009-09-10 20:51:34 +00:00
|
|
|
#if 0
|
2009-07-08 11:49:55 +00:00
|
|
|
static int __dbg_read(void *user, int pid, ut64 addr, ut8 *buf, int len)
|
2009-04-12 23:10:22 +00:00
|
|
|
{
|
2010-03-19 03:02:23 +00:00
|
|
|
RCore *core = (RCore *)user;
|
2009-04-12 23:10:22 +00:00
|
|
|
// TODO: pid not used
|
|
|
|
return r_core_read_at(core, addr, buf, len);
|
|
|
|
}
|
|
|
|
|
2009-07-08 11:49:55 +00:00
|
|
|
static int __dbg_write(void *user, int pid, ut64 addr, const ut8 *buf, int len)
|
2009-04-12 23:10:22 +00:00
|
|
|
{
|
2010-03-19 03:02:23 +00:00
|
|
|
RCore *core = (RCore *)user;
|
2009-04-12 23:10:22 +00:00
|
|
|
// TODO: pid not used
|
|
|
|
return r_core_write_at(core, addr, buf, len);
|
|
|
|
}
|
2009-09-10 20:51:34 +00:00
|
|
|
#endif
|
2009-04-12 23:10:22 +00:00
|
|
|
|
2010-03-19 03:02:23 +00:00
|
|
|
R_API int r_core_init(RCore *core) {
|
2010-05-28 00:44:51 +00:00
|
|
|
static int singleton = R_TRUE;
|
2010-01-31 13:22:27 +00:00
|
|
|
core->ffio = 0;
|
2009-02-05 21:08:46 +00:00
|
|
|
core->oobi = NULL;
|
|
|
|
core->oobi_len = 0;
|
2009-02-18 12:10:59 +00:00
|
|
|
core->yank = NULL;
|
2010-05-19 22:59:42 +00:00
|
|
|
core->reflines = NULL;
|
2009-02-18 12:10:59 +00:00
|
|
|
core->yank_len = 0;
|
|
|
|
core->yank_off = 0LL;
|
2010-05-19 22:59:42 +00:00
|
|
|
core->num = r_num_new (&num_callback, core);
|
|
|
|
//core->num->callback = &num_callback;
|
|
|
|
//core->num->userptr = core;
|
2010-04-09 15:13:35 +00:00
|
|
|
core->cons = r_cons_singleton ();
|
2009-04-01 00:28:13 +00:00
|
|
|
|
|
|
|
/* initialize libraries */
|
2010-05-28 00:44:51 +00:00
|
|
|
if (singleton) {
|
|
|
|
r_cons_new ();
|
|
|
|
r_line_new ();
|
|
|
|
r_cons_singleton()->user_fgets = (void *)myfgets;
|
|
|
|
r_line_hist_load (".radare2_history");
|
|
|
|
singleton = R_FALSE;
|
|
|
|
}
|
2010-05-19 22:59:42 +00:00
|
|
|
core->syscall = r_syscall_new ();
|
|
|
|
core->print = r_print_new ();
|
|
|
|
core->print->printf = (void *)r_cons_printf;
|
|
|
|
core->lang = r_lang_new ();
|
|
|
|
r_lang_define (core->lang, "RCore", "core", core);
|
|
|
|
r_lang_set_user_ptr (core->lang, core);
|
|
|
|
core->anal = r_anal_new ();
|
|
|
|
r_anal_set_user_ptr (core->anal, core);
|
|
|
|
core->assembler = r_asm_new ();
|
|
|
|
r_asm_set_user_ptr (core->assembler, core);
|
|
|
|
core->parser = r_parse_new ();
|
|
|
|
r_parse_set_user_ptr (core->parser, core);
|
|
|
|
core->bin = r_bin_new ();
|
|
|
|
r_bin_set_user_ptr (core->bin, core);
|
|
|
|
core->meta = r_meta_new ();
|
|
|
|
core->io = r_io_new ();
|
|
|
|
core->sign = r_sign_new ();
|
|
|
|
core->search = r_search_new (R_SEARCH_KEYWORD);
|
|
|
|
r_io_undo_enable (core->io, 1, 0); // TODO: configurable via eval
|
2010-03-18 21:22:21 +00:00
|
|
|
//r_cmd_macro_init (&core->macro);
|
2009-02-05 21:08:46 +00:00
|
|
|
core->file = NULL;
|
2010-01-30 13:02:53 +00:00
|
|
|
INIT_LIST_HEAD (&core->files);
|
2010-01-12 01:12:18 +00:00
|
|
|
core->offset = 0LL;
|
2009-02-05 21:08:46 +00:00
|
|
|
core->blocksize = R_CORE_BLOCKSIZE;
|
2010-01-30 13:02:53 +00:00
|
|
|
core->block = (ut8*)malloc (R_CORE_BLOCKSIZE);
|
2010-02-03 17:15:31 +00:00
|
|
|
if (core->block == NULL) {
|
|
|
|
eprintf ("Cannot allocate %d bytes\n", R_CORE_BLOCKSIZE);
|
|
|
|
/* XXX memory leak */
|
|
|
|
return R_FALSE;
|
|
|
|
}
|
2010-01-30 13:02:53 +00:00
|
|
|
r_core_cmd_init (core);
|
2010-05-19 22:59:42 +00:00
|
|
|
core->flags = r_flag_new ();
|
|
|
|
core->dbg = r_debug_new (R_TRUE);
|
2010-06-04 21:47:35 +00:00
|
|
|
core->dbg->anal = core->anal; // XXX: dupped instance.. can cause lost pointerz
|
2010-06-16 19:44:19 +00:00
|
|
|
// core->dbg->anal->reg = core->anal->reg; // XXX: dupped instance.. can cause lost pointerz
|
2010-05-19 22:59:42 +00:00
|
|
|
core->sign->printf = r_cons_printf;
|
|
|
|
core->io->printf = r_cons_printf;
|
|
|
|
core->dbg->printf = r_cons_printf;
|
|
|
|
r_debug_io_bind (core->dbg, core->io);
|
2010-01-30 13:02:53 +00:00
|
|
|
r_core_config_init (core);
|
2009-02-05 21:08:46 +00:00
|
|
|
// XXX fix path here
|
2009-04-01 00:28:13 +00:00
|
|
|
|
|
|
|
/* load plugins */
|
2010-01-26 00:28:33 +00:00
|
|
|
r_core_loadlibs (core);
|
|
|
|
|
|
|
|
// TODO: get arch from r_bin or from native arch
|
2010-05-19 22:59:42 +00:00
|
|
|
r_asm_use (core->assembler, R_SYS_ARCH);
|
|
|
|
r_anal_use (core->anal, R_SYS_ARCH);
|
|
|
|
r_bp_use (core->dbg->bp, R_SYS_ARCH);
|
2010-03-04 00:46:25 +00:00
|
|
|
if (R_SYS_BITS & R_SYS_BITS_64)
|
2010-05-19 22:59:42 +00:00
|
|
|
r_config_set_i (core->config, "asm.bits", 64);
|
2010-03-04 00:46:25 +00:00
|
|
|
else
|
|
|
|
if (R_SYS_BITS & R_SYS_BITS_32)
|
2010-05-19 22:59:42 +00:00
|
|
|
r_config_set_i (core->config, "asm.bits", 32);
|
|
|
|
r_config_set (core->config, "asm.arch", R_SYS_ARCH);
|
2009-02-05 21:08:46 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2010-03-19 03:02:23 +00:00
|
|
|
R_API RCore *r_core_free(RCore *c) {
|
2010-01-26 00:28:33 +00:00
|
|
|
/* TODO: it leaks as shit */
|
2010-01-30 13:02:53 +00:00
|
|
|
free (c);
|
2009-02-05 21:08:46 +00:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2010-06-23 15:30:16 +00:00
|
|
|
R_API int r_core_prompt(RCore *r, int sync) {
|
2010-03-19 03:02:23 +00:00
|
|
|
static char *prevcmd = NULL;
|
2009-02-05 21:08:46 +00:00
|
|
|
int ret;
|
2010-03-19 03:02:23 +00:00
|
|
|
char *cmd;
|
2010-01-09 01:05:04 +00:00
|
|
|
char line[1024];
|
|
|
|
char prompt[32];
|
2010-05-19 22:59:42 +00:00
|
|
|
const char *cmdprompt = r_config_get (r->config, "cmd.prompt");
|
2009-02-05 21:08:46 +00:00
|
|
|
|
2009-02-18 00:43:57 +00:00
|
|
|
if (cmdprompt && cmdprompt[0])
|
2010-02-28 21:58:21 +00:00
|
|
|
ret = r_core_cmd (r, cmdprompt, 0);
|
2009-02-18 00:43:57 +00:00
|
|
|
|
2010-03-24 10:35:41 +00:00
|
|
|
/* XXX : ultraslow */
|
2010-05-19 22:59:42 +00:00
|
|
|
if (!r_config_get_i (r->config, "scr.prompt"))
|
2010-03-24 10:35:41 +00:00
|
|
|
*prompt = 0;
|
2010-05-19 22:59:42 +00:00
|
|
|
else if (r_config_get_i (r->config, "scr.color"))
|
2010-04-14 11:02:23 +00:00
|
|
|
sprintf (prompt, Color_YELLOW"[0x%08"PFMT64x"]> "Color_RESET, r->offset);
|
|
|
|
else sprintf (prompt, "[0x%08"PFMT64x"]> ", r->offset);
|
2010-02-18 15:36:55 +00:00
|
|
|
r_line_singleton()->prompt = prompt;
|
2010-01-09 01:05:04 +00:00
|
|
|
ret = r_cons_fgets (line, sizeof (line), 0, NULL);
|
2010-03-04 11:43:16 +00:00
|
|
|
if (ret == -2)
|
|
|
|
return R_CORE_CMD_EXIT;
|
|
|
|
if (ret == -1)
|
2010-06-23 15:30:16 +00:00
|
|
|
return R_FALSE;
|
2010-03-19 03:02:23 +00:00
|
|
|
if (strcmp (line, ".")) {
|
|
|
|
free (prevcmd);
|
|
|
|
prevcmd = strdup (line);
|
|
|
|
cmd = line;
|
|
|
|
} else cmd = prevcmd;
|
2010-06-23 15:30:16 +00:00
|
|
|
if (sync) {
|
|
|
|
ret = r_core_cmd (r, r->cmdqueue, R_TRUE);
|
|
|
|
r_cons_flush ();
|
|
|
|
} else {
|
|
|
|
r->cmdqueue = cmd;
|
|
|
|
ret = R_TRUE;
|
|
|
|
}
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
R_API int r_core_prompt_exec(RCore *r) {
|
|
|
|
int ret = r_core_cmd (r, r->cmdqueue, R_TRUE);
|
2010-01-09 01:05:04 +00:00
|
|
|
r_cons_flush ();
|
2009-02-05 21:08:46 +00:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2010-03-19 03:02:23 +00:00
|
|
|
R_API int r_core_block_size(RCore *core, ut32 bsize) {
|
2010-03-04 11:43:16 +00:00
|
|
|
int ret = R_FALSE;
|
2009-02-05 21:08:46 +00:00
|
|
|
if (bsize<1)
|
2010-03-04 11:43:16 +00:00
|
|
|
bsize = R_TRUE;
|
2009-02-05 21:08:46 +00:00
|
|
|
else if (bsize> R_CORE_BLOCKSIZE_MAX)
|
|
|
|
bsize = R_CORE_BLOCKSIZE_MAX;
|
2010-03-04 11:43:16 +00:00
|
|
|
else ret = R_TRUE;
|
2010-01-09 01:05:04 +00:00
|
|
|
core->block = realloc (core->block, bsize);
|
2010-04-08 16:01:45 +00:00
|
|
|
if (core->block == NULL) {
|
|
|
|
eprintf ("Oops. cannot allocate that much (%u)\n", bsize);
|
|
|
|
core->block = malloc (R_CORE_BLOCKSIZE);
|
|
|
|
core->blocksize = R_CORE_BLOCKSIZE;
|
|
|
|
} else core->blocksize = bsize;
|
2010-01-09 01:05:04 +00:00
|
|
|
r_core_block_read (core, 0);
|
2009-02-05 21:08:46 +00:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2010-03-19 03:02:23 +00:00
|
|
|
R_API int r_core_seek_align(RCore *core, ut64 align, int times) {
|
2009-03-12 12:30:32 +00:00
|
|
|
int inc = (times>=0)?1:-1;
|
2010-01-12 01:12:18 +00:00
|
|
|
int diff = core->offset%align;
|
|
|
|
ut64 seek = core->offset;
|
2009-03-12 12:30:32 +00:00
|
|
|
|
2010-01-09 01:05:04 +00:00
|
|
|
if (times == 0)
|
|
|
|
diff = -diff;
|
2009-03-12 22:19:58 +00:00
|
|
|
else if (diff) {
|
|
|
|
if (inc>0) diff += align-diff;
|
|
|
|
else diff = -diff;
|
|
|
|
if (times) times -= inc;
|
2009-03-12 12:30:32 +00:00
|
|
|
}
|
2010-01-09 01:05:04 +00:00
|
|
|
while ((times*inc)>0) {
|
2009-03-12 12:30:32 +00:00
|
|
|
times -= inc;
|
|
|
|
diff += align*inc;
|
|
|
|
}
|
2010-02-02 10:09:52 +00:00
|
|
|
if (diff<0 && -diff>seek)
|
|
|
|
seek = diff = 0;
|
2010-01-09 01:05:04 +00:00
|
|
|
return r_core_seek (core, seek+diff, 1);
|
2009-02-05 21:08:46 +00:00
|
|
|
}
|
2009-02-18 00:43:57 +00:00
|
|
|
|
2010-03-19 03:02:23 +00:00
|
|
|
R_API int r_core_seek_delta(RCore *core, st64 addr) {
|
2010-01-12 01:12:18 +00:00
|
|
|
ut64 tmp = core->offset;
|
2009-02-18 00:43:57 +00:00
|
|
|
int ret;
|
|
|
|
if (addr == 0)
|
|
|
|
return R_TRUE;
|
2010-04-14 20:28:45 +00:00
|
|
|
if (addr>0LL) {
|
2009-02-18 00:43:57 +00:00
|
|
|
/* check end of file */
|
2010-01-30 13:02:53 +00:00
|
|
|
if (0) addr = 0; // XXX tmp+addr>) {
|
2010-01-09 01:05:04 +00:00
|
|
|
else addr += tmp;
|
2009-02-18 00:43:57 +00:00
|
|
|
} else {
|
|
|
|
/* check < 0 */
|
2010-02-02 10:09:52 +00:00
|
|
|
if (-addr > tmp) addr = 0;
|
2010-01-30 13:02:53 +00:00
|
|
|
else addr += tmp;
|
2009-02-18 00:43:57 +00:00
|
|
|
}
|
2010-01-12 01:12:18 +00:00
|
|
|
core->offset = addr;
|
2010-01-09 01:05:04 +00:00
|
|
|
ret = r_core_block_read (core, 0);
|
2009-02-18 00:43:57 +00:00
|
|
|
if (ret == -1)
|
2010-01-12 01:12:18 +00:00
|
|
|
core->offset = tmp;
|
2009-02-18 00:43:57 +00:00
|
|
|
return ret;
|
|
|
|
}
|
2010-05-20 07:29:39 +00:00
|
|
|
|
|
|
|
R_API char *r_core_op_str(RCore *core, ut64 addr) {
|
|
|
|
RAsmAop aop;
|
2010-06-04 21:47:35 +00:00
|
|
|
ut8 buf[64];
|
|
|
|
int ret;
|
2010-05-20 07:29:39 +00:00
|
|
|
r_asm_set_pc (core->assembler, addr);
|
|
|
|
r_core_read_at (core, addr, buf, sizeof (buf));
|
|
|
|
ret = r_asm_disassemble (core->assembler, &aop, buf, sizeof (buf));
|
2010-06-04 21:47:35 +00:00
|
|
|
return (ret>0)?strdup (aop.buf_asm): NULL;
|
2010-05-20 07:29:39 +00:00
|
|
|
}
|
|
|
|
|
2010-05-20 23:46:26 +00:00
|
|
|
R_API RAnalOp *r_core_op_anal(RCore *core, ut64 addr) {
|
2010-05-20 07:29:39 +00:00
|
|
|
ut8 buf[64];
|
2010-05-20 23:46:26 +00:00
|
|
|
RAnalOp *aop = R_NEW (RAnalOp);
|
2010-05-20 07:29:39 +00:00
|
|
|
r_core_read_at (core, addr, buf, sizeof (buf));
|
|
|
|
r_anal_aop (core->anal, aop, addr, buf, sizeof (buf));
|
|
|
|
return aop;
|
|
|
|
}
|