static RCore* opencore(const char *f) { const ut64 baddr = UT64_MAX; RCore *c = r_core_new (); if (!c) return NULL; r_core_loadlibs (c, R_CORE_LOADLIBS_ALL, NULL); r_config_set_i (c->config, "io.va", useva); r_config_set_i (c->config, "anal.split", true); if (f) { if (!r_core_file_open (c, f, 0, 0)) { r_core_free (c); return NULL; } r_core_bin_load (c, NULL, baddr); } // TODO: must enable io.va here if wanted .. r_config_set_i (c->config, "io.va", va); if (f && anal_all) { const char *cmd = "aac"; switch (anal_all) { case 1: cmd = "aaa"; break; case 2: cmd = "aaaa"; break; } r_core_cmd0 (c, cmd); } return c; }
R_API int r_core_bin_set_env (RCore *r, RBinFile *binfile) { RBinObject *binobj = binfile ? binfile->o: NULL; RBinInfo *info = binobj ? binobj->info: NULL; if (info) { int va = info->has_va; const char * arch = info->arch; ut16 bits = info->bits; ut64 loadaddr = r_config_get_i (r->config, "bin.laddr"); ut64 baseaddr = binobj->baddr; /* Hack to make baddr work on some corner */ r_config_set_i (r->config, "io.va", (binobj->info)? binobj->info->has_va: 0); r_config_set_i (r->config, "bin.laddr", loadaddr); r_config_set_i (r->config, "bin.baddr", baseaddr); r_config_set (r->config, "asm.arch", arch); r_config_set_i (r->config, "asm.bits", bits); r_config_set (r->config, "anal.arch", arch); if (strlen(info->cpu)) r_config_set (r->config, "anal.cpu", info->cpu); else r_config_set (r->config, "anal.cpu", arch); r_asm_use (r->assembler, arch); r_core_bin_info (r, R_CORE_BIN_ACC_ALL, R_CORE_BIN_SET, va, NULL, loadaddr, NULL); r_core_bin_set_cur (r, binfile); return R_TRUE; } return R_FALSE; }
R_API RAnalHint *r_core_hint_begin (RCore *core, RAnalHint* hint, ut64 at) { // XXX not here static char *hint_arch = NULL; static int hint_bits = 0; if (hint) { r_anal_hint_free (hint); hint = NULL; } hint = r_anal_hint_get (core->anal, at); if (hint_arch) { r_config_set (core->config, "asm.arch", hint_arch); hint_arch = NULL; } if (hint_bits) { r_config_set_i (core->config, "asm.bits", hint_bits); hint_bits = 0; } if (hint) { /* arch */ if (hint->arch) { if (!hint_arch) hint_arch = strdup ( r_config_get (core->config, "asm.arch")); r_config_set (core->config, "asm.arch", hint->arch); } /* bits */ if (hint->bits) { if (!hint_bits) hint_bits = r_config_get_i (core->config, "asm.bits"); r_config_set_i (core->config, "asm.bits", hint->bits); } } return hint; }
static void r_anal_emul_restore(RCore *core, bool *state) { sdb_reset (core->anal->esil->db_trace); r_config_set_i (core->config, "esil.romem", state[ROMEM]); r_config_set_i (core->config, "asm.trace", state[ASM_TRACE]); r_config_set_i (core->config, "anal.trace", state[ANAL_TRACE]); r_config_set_i (core->config, "dbg.trace", state[DBG_TRACE]); r_config_set_i (core->config, "esil.nonull", state[NONULL]); }
static void objc_analyze(RCore *core) { eprintf ("[+] Analyzing searching references to selref\n"); r_core_cmd0 (core, "aar"); if (!strcmp ("arm", r_config_get (core->config, "asm.arch"))) { bool emu_lazy = r_config_get_i (core->config, "emu.lazy"); r_config_set_i (core->config, "emu.lazy", true); r_core_cmd0 (core, "aae"); r_config_set_i (core->config, "emu.lazy", emu_lazy); } }
static RCore* opencore(const char *f) { RCore *c = r_core_new (); r_config_set_i (c->config, "io.va", useva); r_config_set_i (c->config, "anal.split", R_TRUE); if (r_core_file_open (c, f, 0, 0) == NULL) { r_core_free (c); return NULL; } r_core_bin_load (c, NULL); // TODO: must enable io.va here if wanted .. r_config_set_i (c->config, "io.va", va); return c; }
static void objc_analyze(RCore *core) { static const char *oldstr = NULL; oldstr = r_print_rowlog (core->print, "Analyzing searching references to selref"); r_core_cmd0 (core, "aar"); if (!strcmp ("arm", r_config_get (core->config, "asm.arch"))) { bool emu_lazy = r_config_get_i (core->config, "emu.lazy"); r_config_set_i (core->config, "emu.lazy", true); r_core_cmd0 (core, "aae"); r_config_set_i (core->config, "emu.lazy", emu_lazy); } r_print_rowlog_done (core->print, oldstr); }
static RCore* opencore(const char *f) { const ut64 baddr = UT64_MAX; RCore *c = r_core_new (); r_core_loadlibs (c, R_CORE_LOADLIBS_ALL, NULL); r_config_set_i (c->config, "io.va", useva); r_config_set_i (c->config, "anal.split", R_TRUE); if (r_core_file_open (c, f, 0, 0) == NULL) { r_core_free (c); return NULL; } r_core_bin_load (c, NULL, baddr); // TODO: must enable io.va here if wanted .. r_config_set_i (c->config, "io.va", va); return c; }
R_API int r_core_setup_debugger (RCore *r, const char *debugbackend, bool attach) { int pid, *p = NULL; bool is_gdb = !strcmp (debugbackend, "gdb"); RIODesc * fd = r->file ? r_io_desc_get (r->io, r->file->fd) : NULL; const char *prompt = NULL; p = fd ? fd->data : NULL; r_config_set_i (r->config, "cfg.debug", 1); if (!p) { eprintf ("Invalid debug io\n"); return false; } r_config_set (r->config, "io.ff", "true"); r_core_cmdf (r, "dL %s", debugbackend); if (!is_gdb) { pid = r_io_desc_get_pid (fd); r_core_cmdf (r, "dp=%d", pid); if (attach) { r_core_cmdf (r, "dpa %d", pid); } } //this makes to attach twice showing warnings in the output //we get "resource busy" so it seems isn't an issue r_core_cmd (r, ".dr*", 0); /* honor dbg.bep */ { const char *bep = r_config_get (r->config, "dbg.bep"); if (bep) { if (!strcmp (bep, "loader")) { /* do nothing here */ } else if (!strcmp (bep, "entry")) { r_core_cmd (r, "dcu entry0", 0); } else { r_core_cmdf (r, "dcu %s", bep); } } } r_core_cmd (r, "sr PC", 0); /* set the prompt if it's not been set already by the callbacks */ prompt = r_config_get (r->config, "cmd.prompt"); if (prompt && !strcmp (prompt, "")) { if (r_config_get_i (r->config, "dbg.status")) { r_config_set (r->config, "cmd.prompt", ".dr*;drd;sr PC;pi 1;s-"); } else { r_config_set (r->config, "cmd.prompt", ".dr*"); } } r_config_set (r->config, "cmd.vprompt", ".dr*"); return true; }
R_API void r_core_seek_archbits(RCore *core, ut64 addr) { int bits = 0; const char *arch = r_io_section_get_archbits (core->io, addr, &bits); if (!bits && !core->fixedbits) { //if we found bits related with anal hints pick it up __choose_bits_anal_hints (core, addr, &bits); } if (bits && !core->fixedbits) { r_config_set_i (core->config, "asm.bits", bits); } if (arch && !core->fixedarch) { r_config_set (core->config, "asm.arch", arch); } }
R_API boolt r_core_seek(RCore *core, ut64 addr, boolt rb) { RIOSection *newsection; ut64 old = core->offset; ut64 ret; /* XXX unnecesary call */ //r_io_set_fd (core->io, core->file->fd); core->io->section = core->section; // HACK ret = r_io_seek (core->io, addr, R_IO_SEEK_SET); newsection = core->io->section; if (ret == UT64_MAX) { //eprintf ("RET =%d %llx\n", ret, addr); /* XXX handle read errors correctly if (core->ffio) { core->offset = addr; } else return R_FALSE; */ //core->offset = addr; if (!core->io->va) return R_FALSE; memset (core->block, 0xff, core->blocksize); } else core->offset = addr; if (rb) { ret = r_core_block_read (core, 0); if (core->ffio) { if (ret<1 || ret > core->blocksize) memset (core->block, 0xff, core->blocksize); else memset (core->block+ret, 0xff, core->blocksize-ret); ret = core->blocksize; core->offset = addr; } else { if (ret<1) { core->offset = old; //eprintf ("Cannot read block at 0x%08"PFMT64x"\n", addr); } } } if (core->section != newsection) {//&& core->io->section->arch) { int bits = 0;// = core->io->section->bits; const char *arch = r_io_section_get_archbits (core->io, core->offset, &bits); if (arch && bits) { r_config_set (core->config, "asm.arch", arch); r_config_set_i (core->config, "asm.bits", bits); } core->section = core->io->section; } return (ret==-1)? R_FALSE: R_TRUE; }
R_API void r_core_seek_archbits(RCore *core, ut64 addr) { int bits = 0; const char *arch = NULL; RBinObject *o = r_bin_cur_object (core->bin); RBinSection *s = o? r_bin_get_section_at (o, addr, core->io->va): NULL; if (s) { arch = s->arch; bits = s->bits; } if (!bits && !core->fixedbits) { //if we found bits related with anal hints pick it up __choose_bits_anal_hints (core, addr, &bits); } if (bits && !core->fixedbits) { r_config_set_i (core->config, "asm.bits", bits); } if (arch && !core->fixedarch) { r_config_set (core->config, "asm.arch", arch); } }
static int bin_strings (RCore *r, int mode, ut64 baddr, int va) { int rawstr, hasstr, minstr; char *p, *q, str[R_FLAG_NAME_SIZE]; RBinSection *section; RBinString *string; RListIter *iter; RList *list; int i = 0; if (!(hasstr = r_config_get_i (r->config, "bin.strings"))) return 0; if (!r->bin->cur.curplugin) return 0; if (!r->bin->cur.curplugin->info) { if (!r_config_get_i (r->config, "bin.rawstr")) { eprintf ("WARN: Use '-e bin.rawstr=true' or 'rabin2 -zz'" " to find strings on unknown file types\n"); return 0; } } minstr = r_config_get_i (r->config, "bin.minstr"); if (minstr>0) r->bin->minstrlen = minstr; else r_config_set_i (r->config, "bin.minstr", r->bin->minstrlen); if (r->bin->minstrlen==0) return -1; /* code */ if ((list = r_bin_get_strings (r->bin)) == NULL) return R_FALSE; if ((mode & R_CORE_BIN_JSON)) { r_cons_printf ("["); r_list_foreach (list, iter, string) { q = strdup (string->string); //r_name_filter (str, 128); for (p=q; *p; p++) if(*p=='"')*p='\''; r_cons_printf ("%s{\"offset\":%"PFMT64d ",\"length\":%d,\"string\":\"%s\"}", iter->p? ",": "", va? string->rva: string->offset, string->size, q); free (q); }
R_API int r_core_visual_panels(RCore *core) { #define OS_INIT() ostack.size = 0; ostack.panels[0] = 0; #define OS_PUSH(x) if (ostack.size<LIMIT) {ostack.panels[++ostack.size]=x;} #define OS_POP() ((ostack.size>0)? ostack.panels[--ostack.size]:0) int okey, key, wheel; int w, h; int asm_comments = 0; int asm_bytes = 0; n_panels = 0; panels = NULL; callgraph = 0; _core = core; OS_INIT(); w = r_cons_get_size (&h); can = r_cons_canvas_new (w, h); can->linemode = 1; can->color = r_config_get_i (core->config, "scr.color"); // disable colors in disasm because canvas doesnt supports ansi text yet r_config_set_i (core->config, "scr.color", 0); //can->color = 0; if (!can) { eprintf ("Cannot create RCons.canvas context\n"); return R_FALSE; } n_panels = bbPanels (core, &panels); if (!panels) { r_config_set_i (core->config, "scr.color", can->color); free (can); return R_FALSE; } reloadPanels (core); asm_comments = r_config_get_i (core->config, "asm.comments"); r_config_set_i (core->config, "asm.comments", 0); asm_bytes = r_config_get_i (core->config, "asm.bytes"); r_config_set_i (core->config, "asm.bytes", 0); repeat: core->cons->event_data = core; core->cons->event_resize = \ (RConsEvent)r_core_panels_refresh; w = r_cons_get_size (&h); Layout_run (panels); r_core_panels_refresh (core); wheel = r_config_get_i (core->config, "scr.wheel"); if (wheel) r_cons_enable_mouse (R_TRUE); // r_core_graph_inputhandle() okey = r_cons_readchar (); key = r_cons_arrow_to_hjkl (okey); switch (key) { case ' ': case '\n': if (menu_y) { const char *action = menus_sub[menu_x][menu_y-1]; eprintf ("ACTION %s\n", action); if (strstr (action, "New")) { int i; // add new panel for testing for (i=0; panels[i].text; i++) { // find last panel } panels[i].text = strdup ("Test"); panels[i].cmd = r_str_newf ("pxW $r-2"); panels[i].addr = core->offset; panels[i].type = PANEL_TYPE_FRAME; i++; n_panels++; panels[i].text = NULL; } if (strstr (action, "Quit")) { goto beach; } } break; case '?': r_cons_clear00 (); r_cons_printf ("Visual Ascii Art Panels:\n" " ! run r2048 game\n" " . - center graph to the current node\n" " : - run r2 command in prompt\n" " hl - toggle scr.color\n" " HL - move vertical column split\n" " JK - select prev/next panels\n" " jk - scroll/select menu\n" " q - quit, back to visual mode\n" ); r_cons_flush (); r_cons_any_key (NULL); break; case ':': core->vmode = R_FALSE; r_core_visual_prompt_input (core); core->vmode = R_TRUE; break; case 'C': can->color = !!!can->color; //WTF //r_config_swap (core->config, "scr.color"); // refresh graph // reloadPanels (core); break; case '!': r_cons_2048 (); break; case 'j': if (panels[curnode].type == PANEL_TYPE_FLOAT) { if (menus_sub[menu_x][menu_y]) menu_y ++; } break; case 'k': if (panels[curnode].type == PANEL_TYPE_FLOAT) { menu_y --; if (menu_y<0) menu_y = 0; } break; case 'J': curnode++; if (!panels[curnode].text) { curnode--; } break; case 'K': curnode--; if (curnode<0) curnode = 0; break; case 'H': COLW += 4; break; case 'L': COLW -= 4; if (COLW<0) COLW=0; break; case 'h': if (menu_x) { menu_x --; menu_y = menu_y?1:0; } break; case 'l': if (menus[menu_x + 1]) { menu_x ++; menu_y = menu_y?1:0; } break; case 'q': case -1: // EOF goto beach; case 27: // ESC if (r_cons_readchar () == 91) { if (r_cons_readchar () == 90) { } } break; default: //eprintf ("Key %d\n", key); //sleep (1); break; } goto repeat; beach: free (panels); r_config_set_i (core->config, "scr.color", can->color); free (can); r_config_set_i (core->config, "asm.comments", asm_comments); r_config_set_i (core->config, "asm.bytes", asm_bytes); return R_TRUE; }
R_API int r_core_pseudo_code (RCore *core, const char *input) { Sdb *db; RAnalFunction *fcn = r_anal_get_fcn_in (core->anal, core->offset, R_ANAL_FCN_TYPE_NULL); int asmpseudo = r_config_get_i (core->config, "asm.pseudo"); int asmdecode = r_config_get_i (core->config, "asm.decode"); int asmlines = r_config_get_i (core->config, "asm.lines"); int asmbytes = r_config_get_i (core->config, "asm.bytes"); int asmoffset = r_config_get_i (core->config, "asm.offset"); int asmflags = r_config_get_i (core->config, "asm.flags"); int asmfcnlines = r_config_get_i (core->config, "asm.fcnlines"); int asmcomments = r_config_get_i (core->config, "asm.comments"); int asmfunctions = r_config_get_i (core->config, "asm.functions"); if (!fcn) { eprintf ("Cannot find function in 0x%08"PFMT64x"\n", core->offset); return R_FALSE; } r_config_set_i (core->config, "asm.pseudo", 1); r_config_set_i (core->config, "asm.decode", 0); r_config_set_i (core->config, "asm.lines", 0); r_config_set_i (core->config, "asm.bytes", 0); r_config_set_i (core->config, "asm.offset", 0); r_config_set_i (core->config, "asm.flags", 0); r_config_set_i (core->config, "asm.fcnlines", 0); r_config_set_i (core->config, "asm.comments", 0); r_config_set_i (core->config, "asm.functions", 0); db = sdb_new0 (); /* */ // walk all basic blocks // define depth level for each block // use it for indentation // asm.pseudo=true // asm.decode=true RAnalBlock *bb = r_list_first (fcn->bbs); char indentstr[1024]; int n_bb = r_list_length (fcn->bbs); r_cons_printf ("function %s () {", fcn->name); int indent = 1; int nindent = 1; do { #define I_TAB 4 #define K_ELSE(x) sdb_fmt(0,"else.%"PFMT64x,x) #define K_INDENT(x) sdb_fmt(0,"loc.%"PFMT64x,x) #define SET_INDENT(x) { memset (indentstr, ' ', x*I_TAB); indentstr [(x*I_TAB)-2] = 0; } if (!bb) break; r_cons_push (); char *code = r_core_cmd_str (core, sdb_fmt(0, "pDI %d @ 0x%08"PFMT64x"\n", bb->size, bb->addr)); r_cons_pop (); memset (indentstr, ' ', indent*I_TAB); indentstr [(indent*I_TAB)-2] = 0; code = r_str_prefix_all (code, indentstr); code[strlen(code)-1] = 0; // chop last newline //r_cons_printf ("\n%s loc_0x%llx:\n", indentstr, bb->addr); //if (nindent != indent) { // r_cons_printf ("\n%s loc_0x%llx:\n", indentstr, bb->addr); //} r_cons_printf ("\n%s loc_0x%llx:\n", indentstr, bb->addr); indentstr[(indent*I_TAB)-2] = 0; r_cons_printf ("\n%s", code); free (code); if (sdb_get (db, K_INDENT(bb->addr), 0)) { // already analyzed, go pop and continue // XXX check if cant pop //eprintf ("%s// 0x%08llx already analyzed\n", indentstr, bb->addr); ut64 addr = sdb_array_pop_num (db, "indent", NULL); if (addr==UT64_MAX) { int i; nindent = 1; for (i=indent; i!=nindent; i--) { SET_INDENT (i); r_cons_printf ("\n%s}", indentstr); } r_cons_printf ("\n%sreturn;\n", indentstr); break; } if (sdb_num_get (db, K_ELSE(bb->addr), 0)) { r_cons_printf ("\n%s} else {", indentstr); } else { r_cons_printf ("\n%s}", indentstr); } r_cons_printf ("\n%s goto loc_0x%llx", indentstr, addr); bb = r_anal_bb_from_offset (core->anal, addr); if (!bb) { eprintf ("failed block\n"); break; } //eprintf ("next is %llx\n", addr); nindent = sdb_num_get (db, K_INDENT(addr), NULL); if (indent>nindent) { int i; for (i=indent; i!=nindent; i--) { SET_INDENT (i); r_cons_printf ("\n%s}", indentstr); } } indent = nindent; } else { sdb_set (db, K_INDENT(bb->addr), "passed", 0); if (bb->jump != UT64_MAX) { int swap = 1; // TODO: determine which branch take first ut64 jump = swap? bb->jump: bb->fail; ut64 fail = swap? bb->fail: bb->jump; // if its from another function chop it! RAnalFunction *curfcn = r_anal_get_fcn_in (core->anal, jump, R_ANAL_FCN_TYPE_NULL); if (curfcn != fcn) { // chop that branch r_cons_printf ("\n // chop\n"); break; } if (sdb_get (db, K_INDENT(jump), 0)) { // already tracekd if (!sdb_get (db, K_INDENT(fail), 0)) { bb = r_anal_bb_from_offset (core->anal, fail); } } else { bb = r_anal_bb_from_offset (core->anal, jump); if (!bb) { eprintf ("failed to retrieve blcok at 0x%"PFMT64x"\n", jump); break; } if (fail != UT64_MAX) { // do not push if already pushed indent++; if (sdb_get (db, K_INDENT(bb->fail), 0)) { /* do nothing here */ eprintf ("BlockAlready 0x%"PFMT64x"\n", bb->addr); } else { // r_cons_printf (" { RADICAL %llx\n", bb->addr); sdb_array_push_num (db, "indent", fail, 0); sdb_num_set (db, K_INDENT(fail), indent, 0); sdb_num_set (db, K_ELSE(fail), 1, 0); r_cons_printf (" {"); } } else { r_cons_printf (" do"); sdb_array_push_num (db, "indent", jump, 0); sdb_num_set (db, K_INDENT(jump), indent, 0); sdb_num_set (db, K_ELSE(jump), 1, 0); r_cons_printf (" {"); indent++; } } } else { ut64 addr = sdb_array_pop_num (db, "indent", NULL); if (addr==UT64_MAX) { r_cons_printf ("\nbreak\n"); break; } bb = r_anal_bb_from_offset (core->anal, addr); nindent = sdb_num_get (db, K_INDENT(addr), NULL); if (indent>nindent) { int i; for (i=indent; i!=nindent; i--) { SET_INDENT (i); r_cons_printf ("\n%s}", indentstr); } } if (nindent != indent) { r_cons_printf ("\n%s} else {\n", indentstr); } indent = nindent; } } //n_bb --; } while (n_bb>0); r_cons_printf ("}\n"); r_cons_flush (); r_config_set_i (core->config, "asm.pseudo", asmpseudo); r_config_set_i (core->config, "asm.decode", asmdecode); r_config_set_i (core->config, "asm.lines", asmlines); r_config_set_i (core->config, "asm.bytes", asmbytes); r_config_set_i (core->config, "asm.offset", asmoffset); r_config_set_i (core->config, "asm.flags", asmflags); r_config_set_i (core->config, "asm.fcnlines", asmfcnlines); r_config_set_i (core->config, "asm.comments", asmcomments); r_config_set_i (core->config, "asm.functions", asmfunctions); sdb_free (db); return R_TRUE; }
int main(int argc, char **argv) { const char *addr = NULL; RCore *c, *c2; RDiff *d; const char *arch = NULL; int bits = 0; char *file, *file2; ut8 *bufa, *bufb; int o, sza, szb, /*diffmode = 0,*/ delta = 0; int mode = MODE_DIFF; int diffops = 0; int threshold = -1; int gdiff_mode = 0; double sim; while ((o = getopt (argc, argv, "a:b:Cnpg:Ojrhcdsvxt:")) != -1) { switch (o) { case 'a': arch = optarg; break; case 'b': bits = atoi (optarg); break; case 'p': useva = R_FALSE; break; case 'r': diffmode = 'r'; break; case 'g': mode = MODE_GRAPH; addr = optarg; break; case 'c': showcount = 1; break; case 'C': mode = MODE_CODE; gdiff_mode++; break; case 'n': showbare = R_TRUE; break; case 'O': diffops = 1; break; case 't': threshold = atoi (optarg); printf ("%s\n", optarg); break; case 'd': delta = 1; break; case 'h': return show_help (1); case 's': mode = MODE_DIST; break; case 'x': mode = MODE_COLS; break; case 'v': printf ("radiff2 v"R2_VERSION"\n"); return 0; case 'j': diffmode = 'j'; break; default: return show_help (0); } } if (argc<3 || optind+2>argc) return show_help (0); if (optind<argc) { file = argv[optind]; } else { file = NULL; } if (optind+1<argc) { file2 = argv[optind+1]; } else { file2 = NULL; } switch (mode) { case MODE_GRAPH: case MODE_CODE: c = opencore (file); if (!c) eprintf ("Cannot open '%s'\n", r_str_get (file)); c2 = opencore (file2); if (!c || !c2) { eprintf ("Cannot open '%s'\n", r_str_get (file2)); return 1; } if (arch) { r_config_set (c->config, "asm.arch", arch); r_config_set (c2->config, "asm.arch", arch); } if (bits) { r_config_set_i (c->config, "asm.bits", bits); r_config_set_i (c2->config, "asm.bits", bits); } r_config_set_i (c->config, "diff.bare", showbare); r_config_set_i (c2->config, "diff.bare", showbare); r_anal_diff_setup_i (c->anal, diffops, threshold, threshold); r_anal_diff_setup_i (c2->anal, diffops, threshold, threshold); if (mode == MODE_GRAPH) { char *words = strdup (addr); char *second = strstr (words, ","); if (second) { ut64 off; *second++ = 0; off = r_num_math (c->num, words); // define the same function at each offset r_core_anal_fcn (c, off, UT64_MAX, R_ANAL_REF_TYPE_NULL, 0); r_core_anal_fcn (c2, r_num_math (c2->num, second), UT64_MAX, R_ANAL_REF_TYPE_NULL, 0); r_core_gdiff (c, c2, R_FALSE); // compute the diff r_core_anal_graph (c, off, R_CORE_ANAL_GRAPHBODY | R_CORE_ANAL_GRAPHDIFF); } else { r_core_anal_fcn (c, r_num_math (c->num, words), UT64_MAX, R_ANAL_REF_TYPE_NULL, 0); r_core_anal_fcn (c2, r_num_math (c2->num, words), UT64_MAX, R_ANAL_REF_TYPE_NULL, 0); r_core_gdiff (c, c2, gdiff_mode); r_core_anal_graph (c, r_num_math (c->num, addr), R_CORE_ANAL_GRAPHBODY | R_CORE_ANAL_GRAPHDIFF); } free (words); } else { r_core_gdiff (c, c2, gdiff_mode); r_core_diff_show (c, c2); } r_cons_flush (); return 0; } bufa = (ut8*)r_file_slurp (file, &sza); if (!bufa) { eprintf ("radiff2: Cannot open %s\n", r_str_get (file)); return 1; } bufb = (ut8*)r_file_slurp (file2, &szb); if (!bufb) { eprintf ("radiff2: Cannot open: %s\n", r_str_get (file2)); free (bufa); return 1; } switch (mode) { case MODE_COLS: { int cols = (r_cons_get_size (NULL)>112)?16:8; dump_cols (bufa, sza, bufb, szb, cols); } break; case MODE_DIFF: d = r_diff_new (0LL, 0LL); r_diff_set_delta (d, delta); if (diffmode == 'j') { printf("{\"files\":[{\"filename\":\"%s\", \"size\":%d, \"sha256\":\"", file, sza); handle_sha256 (bufa, sza); printf("\"},\n{\"filename\":\"%s\", \"size\":%d, \"sha256\":\"", file2, szb); handle_sha256 (bufb, szb); printf("\"}],\n"); printf("\"changes\":["); } r_diff_set_callback (d, &cb, 0);//(void *)(size_t)diffmode); r_diff_buffers (d, bufa, sza, bufb, szb); if (diffmode == 'j') printf("]\n"); r_diff_free (d); break; case MODE_DIST: r_diff_buffers_distance (NULL, bufa, sza, bufb, szb, &count, &sim); printf ("similarity: %.2f\n", sim); printf ("distance: %d\n", count); break; } if (diffmode == 'j' && showcount) printf (",\"count\":%d}\n",count); else if (showcount && diffmode != 'j') printf ("%d\n", count); else if (!showcount && diffmode == 'j') printf ("}\n"); free (bufa); free (bufb); return 0; }
R_API int r_core_visual_cmd(RCore *core, int ch) { RAsmOp op; ut64 offset = core->offset; char buf[4096]; int i, ret, offscreen, cols = core->print->cols, delta = 0; ch = r_cons_arrow_to_hjkl (ch); ch = visual_nkey (core, ch); if (ch<2) return 1; // do we need hotkeys for data references? not only calls? if (ch>='0'&& ch<='9') { ut64 off = core->asmqjmps[ch-'0']; if (off != UT64_MAX) { int delta = R_ABS ((st64)off-(st64)offset); r_io_sundo_push (core->io, offset); if (curset && delta<100) { cursor = delta; } else { r_core_visual_seek_animation (core, off); //r_core_seek (core, off, 1); } r_core_block_read (core, 1); } } else switch (ch) { case 0x0d: { r_cons_enable_mouse (R_TRUE); RAnalOp *op = r_core_anal_op (core, core->offset+cursor); if (op) { if (op->type == R_ANAL_OP_TYPE_JMP || op->type == R_ANAL_OP_TYPE_CJMP || op->type == R_ANAL_OP_TYPE_CALL) { r_io_sundo_push (core->io, offset); r_core_visual_seek_animation(core, op->jump); } } r_anal_op_free (op); } break; case 90: // shift+tab if (!strcmp (printfmt[0], "x")) printfmt[0] = "pxa"; else printfmt[0] = "x"; break; case 9: // tab { // XXX: unify diff mode detection ut64 f = r_config_get_i (core->config, "diff.from"); ut64 t = r_config_get_i (core->config, "diff.to"); if (f == t && f == 0) { core->print->col = core->print->col==1? 2: 1; } else { ut64 delta = offset - f; r_core_seek (core, t+delta, 1); r_config_set_i (core->config, "diff.from", t); r_config_set_i (core->config, "diff.to", f); } } break; case 'a': if (core->file && !(core->file->rwx & 2)) { r_cons_printf ("\nFile has been opened in read-only mode. Use -w flag\n"); r_cons_any_key (); return R_TRUE; } r_cons_printf ("Enter assembler opcodes separated with ';':\n"); showcursor (core, R_TRUE); r_cons_flush (); r_cons_set_raw (R_FALSE); strcpy (buf, "wa "); r_line_set_prompt (":> "); if (r_cons_fgets (buf+3, 1000, 0, NULL) <0) buf[0]='\0'; if (*buf) { if (curset) r_core_seek (core, core->offset + cursor, 0); r_core_cmd (core, buf, R_TRUE); if (curset) r_core_seek (core, core->offset - cursor, 1); } showcursor (core, R_FALSE); r_cons_set_raw (R_TRUE); break; case '!': r_cons_2048(); break; case 'o': visual_offset (core); break; case 'A': { int oc = curset; ut64 off = curset? core->offset+cursor : core->offset; curset = 0; r_core_visual_asm (core, off); curset = oc; } break; case 'c': setcursor (core, curset?0:1); break; case 'C': color = color? 0: 1; r_config_set_i (core->config, "scr.color", color); break; case 'd': r_core_visual_define (core); break; case 'D': setdiff (core); break; case 'f': { int range, min, max; char name[256], *n; r_line_set_prompt ("flag name: "); showcursor (core, R_TRUE); if (r_cons_fgets (name, sizeof (name), 0, NULL) >=0 && *name) { n = r_str_chop (name); if (*name=='-') { if (*n) r_flag_unset (core->flags, n+1, NULL); } else { if (ocursor != -1) { min = R_MIN (cursor, ocursor); max = R_MAX (cursor, ocursor); } else { min = max = cursor; } range = max-min+1; if (range<1) range = 1; if (*n) r_flag_set (core->flags, n, core->offset + min, range, 1); } } } showcursor (core, R_FALSE); break; case 'F': r_flag_unset_i (core->flags, core->offset + cursor, NULL); break; case 'n': r_core_seek_next (core, r_config_get (core->config, "scr.nkey")); break; case 'N': r_core_seek_previous (core, r_config_get (core->config, "scr.nkey")); break; case 'i': case 'I': if (core->file && !(core->file->rwx & 2)) { r_cons_printf ("\nFile has been opened in read-only mode. Use -w flag\n"); r_cons_any_key (); return R_TRUE; } showcursor (core, R_TRUE); r_cons_flush (); r_cons_set_raw (0); if (ch=='I') { strcpy (buf, "wow "); r_line_set_prompt ("insert hexpair block: "); if (r_cons_fgets (buf+4, sizeof (buf)-5, 0, NULL) <0) buf[0]='\0'; char *p = strdup (buf); int cur = core->print->cur; if (cur>=core->blocksize) cur = core->print->cur-1; snprintf (buf, sizeof (buf), "%s @ $$0!%i", p, core->blocksize-cursor); r_core_cmd (core, buf, 0); free (p); break; } delta = (ocursor!=-1)? R_MIN (cursor, ocursor): cursor; if (core->print->col==2) { strcpy (buf, "\"w "); r_line_set_prompt ("insert string: "); if (r_cons_fgets (buf+3, sizeof (buf)-4, 0, NULL) <0) buf[0]='\0'; strcat (buf, "\""); } else { r_line_set_prompt ("insert hex: "); if (ocursor != -1) { int bs = R_ABS (cursor-ocursor)+1; core->blocksize = bs; strcpy (buf, "wow "); } else { strcpy (buf, "wx "); } if (r_cons_fgets (buf+strlen (buf), sizeof (buf)-strlen (buf), 0, NULL) <0) buf[0]='\0'; } if (curset) r_core_seek (core, core->offset + delta, 0); r_core_cmd (core, buf, 1); if (curset) r_core_seek (core, offset, 1); r_cons_set_raw (1); showcursor (core, R_FALSE); break; case 'R': r_core_cmd0 (core, "ecr"); break; case 'e': r_core_visual_config (core); break; case 'E': r_core_visual_colors (core); break; case 'M': r_core_visual_mounts (core); break; case 't': r_core_visual_trackflags (core); break; case 'x': { int count = 0; RList *xrefs = NULL; RAnalRef *refi; RListIter *iter; RAnalFunction *fun; if ((xrefs = r_anal_xref_get (core->anal, core->offset))) { r_cons_gotoxy (1, 1); r_cons_printf ("[GOTO XREF]> \n"); if (r_list_empty (xrefs)) { r_cons_printf ("\tNo XREF found at 0x%"PFMT64x"\n", core->offset); r_cons_any_key (); r_cons_clear00 (); } else { r_list_foreach (xrefs, iter, refi) { fun = r_anal_fcn_find (core->anal, refi->addr, R_ANAL_FCN_TYPE_NULL); r_cons_printf (" [%i] 0x%08"PFMT64x" %s XREF 0x%08"PFMT64x" (%s) \n", count, refi->at, refi->type==R_ANAL_REF_TYPE_CODE?"CODE (JMP)": refi->type==R_ANAL_REF_TYPE_CALL?"CODE (CALL)":"DATA", refi->addr, fun?fun->name:"unk"); if (++count > 9) break; } } } else xrefs = NULL;
int main(int argc, char **argv) { const char *query = NULL; int c, bits = 0, actions_done = 0, actions = 0, action = ACTION_UNK; char *homeplugindir = r_str_home (R2_HOMEDIR"/plugins"); char *ptr, *arch = NULL, *arch_name = NULL; const char *op = NULL; RCoreBinFilter filter; RCore core; RCoreFile *cf = NULL; int xtr_idx = 0; // load all files if extraction is necessary. int fd = -1; int rawstr = 0; r_core_init (&core); bin = core.bin; l = r_lib_new ("radare_plugin"); r_lib_add_handler (l, R_LIB_TYPE_BIN, "bin plugins", &__lib_bin_cb, &__lib_bin_dt, NULL); r_lib_add_handler (l, R_LIB_TYPE_BIN_XTR, "bin xtr plugins", &__lib_bin_xtr_cb, &__lib_bin_xtr_dt, NULL); /* load plugins everywhere */ r_lib_opendir (l, getenv ("LIBR_PLUGINS")); r_lib_opendir (l, homeplugindir); r_lib_opendir (l, LIBDIR"/radare2/"R2_VERSION); #define is_active(x) (action&x) #define set_action(x) actions++; action |=x while ((c = getopt (argc, argv, "jgqAf:a:B:b:c:Ck:dMm:n:N:@:isSIHelRwO:o:rvLhxzZ")) != -1) { switch (c) { case 'g': set_action (ACTION_CLASSES); set_action (ACTION_IMPORTS); set_action (ACTION_SYMBOLS); set_action (ACTION_SECTIONS); set_action (ACTION_STRINGS); set_action (ACTION_SIZE); set_action (ACTION_INFO); set_action (ACTION_FIELDS); set_action (ACTION_DWARF); set_action (ACTION_ENTRIES); set_action (ACTION_MAIN); set_action (ACTION_LIBS); set_action (ACTION_RELOCS); set_action (ACTION_EXTRACT); break; case 'q': rad = R_CORE_BIN_SIMPLE; break; case 'j': rad = R_CORE_BIN_JSON; break; case 'A': set_action (ACTION_LISTARCHS); break; case 'a': if (optarg) arch = optarg; break; case 'c': if (!optarg) { eprintf ("Missing argument for -c"); return 1; } set_action (ACTION_CREATE); create = strdup (optarg); break; case 'k': query = optarg; break; case 'C': set_action (ACTION_CLASSES); break; case 'f': if (optarg) arch_name = strdup (optarg); break; case 'b': bits = r_num_math (NULL, optarg); break; case 'm': at = r_num_math (NULL, optarg); set_action (ACTION_SRCLINE); break; case 'i': set_action (ACTION_IMPORTS); break; case 's': set_action (ACTION_SYMBOLS); break; case 'S': set_action (ACTION_SECTIONS); break; case 'z': if (is_active (ACTION_STRINGS)) { rawstr = R_TRUE; } else set_action (ACTION_STRINGS); break; case 'Z': set_action (ACTION_SIZE); break; case 'I': set_action (ACTION_INFO); break; case 'H': set_action (ACTION_FIELDS); break; case 'd': set_action (ACTION_DWARF); break; case 'e': set_action (ACTION_ENTRIES); break; case 'M': set_action (ACTION_MAIN); break; case 'l': set_action (ACTION_LIBS); break; case 'R': set_action (ACTION_RELOCS); break; case 'x': set_action (ACTION_EXTRACT); break; case 'w': rw = R_TRUE; break; case 'O': op = optarg; set_action (ACTION_OPERATION); if (op && !strcmp (op, "help")) { printf ("Operation string:\n" " Dump symbols: d/s/1024\n" " Dump section: d/S/.text\n" " Resize section: r/.data/1024\n"); return 0; } if (optind==argc) { eprintf ("Missing filename\n"); return 1; } break; case 'o': output = optarg; break; case 'r': rad = R_TRUE; break; case 'v': va = R_TRUE; break; case 'L': r_bin_list (bin); return 1; case 'B': baddr = r_num_math (NULL, optarg); break; case '@': at = r_num_math (NULL, optarg); break; case 'n': name = optarg; break; case 'N': bin->minstrlen = r_num_math (NULL, optarg); break; //case 'V': return blob_version ("rabin2"); case 'h': return rabin_show_help (1); default: action |= ACTION_HELP; } } file = argv[optind]; if (!query) if (action & ACTION_HELP || action == ACTION_UNK || file == NULL) { if (va) return blob_version ("rabin2"); return rabin_show_help (0); } if (arch) { ptr = strchr (arch, '_'); if (ptr) { *ptr = '\0'; bits = r_num_math (NULL, ptr+1); } } if (action & ACTION_CREATE) { // TODO: move in a function outside RBuffer *b; int datalen, codelen; ut8 *data = NULL, *code = NULL; char *p2, *p = strchr (create, ':'); if (!p) { eprintf ("Invalid format for -c flag. Use 'format:codehexpair:datahexpair'\n"); return 1; } *p++ = 0; p2 = strchr (p, ':'); if (p2) { // has data *p2++ = 0; data = malloc (strlen (p2)+1); datalen = r_hex_str2bin (p2, data); } else { data = NULL; datalen = 0; } code = malloc (strlen (p)+1); if (!code) { return 1; } codelen = r_hex_str2bin (p, code); if (!arch) arch = "x86"; if (!bits) bits = 32; if (!r_bin_use_arch (bin, arch, bits, create)) { eprintf ("Cannot set arch\n"); return 1; } b = r_bin_create (bin, code, codelen, data, datalen); if (b) { if (r_file_dump (file, b->buf, b->length)) { eprintf ("dumped %d bytes in '%s'\n", b->length, file); r_file_chmod (file, "+x", 0); } else eprintf ("error dumping into a.out\n"); r_buf_free (b); } else eprintf ("Cannot create binary for this format '%s'.\n", create); r_bin_free (bin); return 0; } r_config_set_i (core.config, "bin.rawstr", rawstr); cf = r_core_file_open (&core, file, R_IO_READ, 0); fd = cf ? r_core_file_cur_fd (&core) : -1; if (!cf || fd == -1) { eprintf ("r_core: Cannot open file\n"); return 1; } if (!r_bin_load (bin, file, baddr, 0, xtr_idx, fd, rawstr)) { if (!r_bin_load (bin, file, baddr, 0, xtr_idx, fd, rawstr)) { eprintf ("r_bin: Cannot open file\n"); return 1; } } if (query) { if (!strcmp (query, "-")) { __sdb_prompt (bin->cur->sdb); } else sdb_query (bin->cur->sdb, query); return 0; } // XXX: TODO move this to libr/core/bin.c if (action & ACTION_LISTARCHS || ((arch || bits || arch_name) && !r_bin_select (bin, arch, bits, arch_name))) { if (rad == R_CORE_BIN_JSON) { int i; printf ("["); for (i = 0; i < bin->narch; i++) { if (r_bin_select_idx (bin, bin->file, i)) { RBinObject *o = r_bin_cur_object (bin); RBinInfo *info = o ? o->info : NULL; printf ("%s{\"arch\":\"%s\",\"bits\":%d," "\"offset\":%"PFMT64d",\"machine\":\"%s\"}", i?",":"",info->arch, info->bits, bin->cur->offset, info->machine); } } printf ("]"); } else r_bin_list_archs (bin, 1); free (arch_name); } if (baddr != 0LL) { r_bin_set_baddr (bin, baddr); bin->cur->o->baddr = baddr; } core.bin = bin; filter.offset = at; filter.name = name; r_cons_new ()->is_interactive = R_FALSE; #define isradjson (rad==R_CORE_BIN_JSON&&actions>0) #define run_action(n,x,y) {\ if (action&x) {\ if (isradjson) r_cons_printf ("\"%s\":",n);\ if (!r_core_bin_info (&core, y, rad, va, &filter, 0)) {\ if (isradjson) r_cons_printf("false");\ };\ actions_done++;\ if (isradjson) r_cons_printf (actions==actions_done? "":",");\ }\ } if (isradjson) r_cons_printf ("{"); run_action ("sections", ACTION_SECTIONS, R_CORE_BIN_ACC_SECTIONS); run_action ("entries", ACTION_ENTRIES, R_CORE_BIN_ACC_ENTRIES); run_action ("main", ACTION_MAIN, R_CORE_BIN_ACC_MAIN); run_action ("imports", ACTION_IMPORTS, R_CORE_BIN_ACC_IMPORTS); run_action ("classes", ACTION_CLASSES, R_CORE_BIN_ACC_CLASSES); run_action ("symbols", ACTION_SYMBOLS, R_CORE_BIN_ACC_SYMBOLS); run_action ("strings", ACTION_STRINGS, R_CORE_BIN_ACC_STRINGS); run_action ("info", ACTION_INFO, R_CORE_BIN_ACC_INFO); run_action ("fields", ACTION_FIELDS, R_CORE_BIN_ACC_FIELDS); run_action ("libs", ACTION_LIBS, R_CORE_BIN_ACC_LIBS); run_action ("relocs", ACTION_RELOCS, R_CORE_BIN_ACC_RELOCS); run_action ("dwarf", ACTION_DWARF, R_CORE_BIN_ACC_DWARF); run_action ("size", ACTION_SIZE, R_CORE_BIN_ACC_SIZE); if (action&ACTION_SRCLINE) rabin_show_srcline (at); if (action&ACTION_EXTRACT) rabin_extract ((arch==NULL && arch_name==NULL && bits==0)); if (op != NULL && action&ACTION_OPERATION) rabin_do_operation (op); if (isradjson) printf ("}"); r_cons_flush (); r_core_fini (&core); return 0; }
static int cmd_seek(void *data, const char *input) { RCore *core = (RCore *)data; char *cmd, *p; ut64 off; if (*input=='r') { if (input[1] && input[2]) { if (core->io->debug) { off = r_debug_reg_get (core->dbg, input+2); r_io_sundo_push (core->io, core->offset); r_core_seek (core, off, 1); } else { RReg *orig = core->dbg->reg; core->dbg->reg = core->anal->reg; off = r_debug_reg_get (core->dbg, input+2); core->dbg->reg = orig; r_core_seek (core, off, 1); } } else eprintf ("|Usage| 'sr pc' seek to program counter register\n"); } else if (*input) { const char *inputnum = strchr (input+1, ' '); int sign = 1; inputnum = inputnum? inputnum+1: input+1; off = r_num_math (core->num, inputnum); if (*inputnum== '-') off = -off; #if 0 if (input[0]!='/' && inputnum && isalpha (inputnum[0]) && off == 0) { if (!r_flag_get (core->flags, inputnum)) { eprintf ("Cannot find address for '%s'\n", inputnum); return R_FALSE; } } #endif if (input[0]==' ') { switch (input[1]) { case '-': sign=-1; case '+': input++; break; } } switch (*input) { case 'C': if (input[1]=='*') { r_core_cmd0 (core, "C*~^\"CC"); } else if (input[1]==' ') { typedef struct { ut64 addr; char *str; } MetaCallback; int count = 0; MetaCallback cb = { 0, NULL }; ut64 addr; char key[128]; const char *val, *comma; char *list = sdb_get (core->anal->sdb_meta, "meta.C", 0); char *str, *next, *cur = list; if (list) { for (;;) { cur = sdb_anext (cur, &next); addr = sdb_atoi (cur); snprintf (key, sizeof (key)-1, "meta.C.0x%"PFMT64x, addr); val = sdb_const_get (core->anal->sdb_meta, key, 0); if (val) { comma = strchr (val, ','); if (comma) { str = (char *)sdb_decode (comma+1, 0); if (strstr (str, input+2)) { r_cons_printf ("0x%08"PFMT64x" %s\n", addr, str); count++; cb.addr = addr; free (cb.str); cb.str = str; } else free (str); } } else eprintf ("sdb_const_get key not found '%s'\n", key); if (!next) break; cur = next; } } switch (count) { case 0: eprintf ("No matching comments\n"); break; case 1: off = cb.addr; r_io_sundo_push (core->io, core->offset); r_core_seek (core, off, 1); r_core_block_read (core, 0); break; default: eprintf ("Too many results\n"); break; } free (cb.str); } else eprintf ("Usage: sC[?*] comment-grep\n" "sC* list all comments\n" "sC const seek to comment matching 'const'\n"); break; case ' ': r_io_sundo_push (core->io, core->offset); r_core_seek (core, off*sign, 1); r_core_block_read (core, 0); break; case '/': { const char *pfx = r_config_get (core->config, "search.prefix"); //kwidx cfg var is ignored int kwidx = core->search->n_kws; //(int)r_config_get_i (core->config, "search.kwidx")-1; if (kwidx<0) kwidx = 0; switch (input[1]) { case ' ': case 'x': r_config_set_i (core->config, "search.count", 1); r_core_cmdf (core, "s+1; p8 ; .%s;s-1;s %s%d_0;f-%s%d_0", input, pfx, kwidx, pfx, kwidx, pfx, kwidx); r_config_set_i (core->config, "search.count", 0); break; default: eprintf ("unknown search method\n"); break; } } break; case '.': for (input++;*input=='.';input++); r_core_seek_base (core, input); break; case '*': r_io_sundo_list (core->io); break; case '+': if (input[1]!='\0') { int delta = (input[1]=='+')? core->blocksize: off; r_io_sundo_push (core->io, core->offset); r_core_seek_delta (core, delta); } else { off = r_io_sundo_redo (core->io); if (off != UT64_MAX) r_core_seek (core, off, 0); } break; case '-': if (input[1]!='\0') { int delta = (input[1]=='-') ? -core->blocksize: -off; r_io_sundo_push (core->io, core->offset); r_core_seek_delta (core, delta); } else { off = r_io_sundo (core->io, core->offset); if (off != UT64_MAX) r_core_seek (core, off, 0); } break; case 'n': r_io_sundo_push (core->io, core->offset); r_core_seek_next (core, r_config_get (core->config, "scr.nkey")); break; case 'p': r_io_sundo_push (core->io, core->offset); r_core_seek_previous (core, r_config_get (core->config, "scr.nkey")); break; case 'a': off = core->blocksize; if (input[1]&&input[2]) { cmd = strdup (input); p = strchr (cmd+2, ' '); if (p) { off = r_num_math (core->num, p+1);; *p = '\0'; } cmd[0] = 's'; // perform real seek if provided r_cmd_call (core->rcmd, cmd); free (cmd); } r_io_sundo_push (core->io, core->offset); r_core_seek_align (core, off, 0); break; case 'b': if (off == 0) off = core->offset; r_io_sundo_push (core->io, core->offset); r_core_anal_bb_seek (core, off); break; case 'f': if (strlen(input) > 2 && input[1]==' ') { RAnalFunction *fcn = r_anal_fcn_find_name (core->anal, input+2); if (fcn) { r_core_seek (core, fcn->addr, 1); } break; } RAnalFunction *fcn = r_anal_fcn_find (core->anal, core->offset, 0); if (fcn) { r_core_seek (core, fcn->addr+fcn->size, 1); } break; case 'o': { RAnalOp op; int val=0, ret, i, n = r_num_math (core->num, input+1); if (n==0) n = 1; if (n<0) { int ret = prevopsz (core, n); ret = r_anal_op (core->anal, &op, core->offset, core->block, core->blocksize); val += ret; } else for (val=i=0; i<n; i++) { ret = r_anal_op (core->anal, &op, core->offset, core->block, core->blocksize); if (ret<1) break; r_core_seek_delta (core, ret); val += ret; } core->num->value = val; } break; case 'g': { RIOSection *s = r_io_section_vget (core->io, core->offset); if (s) r_core_seek (core, s->vaddr, 1); else r_core_seek (core, 0, 1); } break; case 'G': { RIOSection *s = r_io_section_vget (core->io, core->offset); // XXX: this +2 is a hack. must fix gap between sections if (s) r_core_seek (core, s->vaddr+s->size+2, 1); else r_core_seek (core, core->file->size, 1); } break; case '?': { const char * help_message[] = { "Usage: s", "", " # Seek commands", "s", "", "Print current address", "s", " addr", "Seek to address", "s-", "", "Undo seek", "s-", " n", "Seek n bytes backward", "s--", "", "Seek blocksize bytes backward", "s+", "", "Redo seek", "s+", " n", "Seek n bytes forward", "s++", "", "Seek blocksize bytes forward", "s*", "", "List undo seek history", "s/", " DATA", "Search for next occurrence of 'DATA'", "s/x", " 9091", "Search for next occurrence of \\x90\\x91", "s.", "hexoff", "Seek honoring a base from core->offset", "sa", " [[+-]a] [asz]", "Seek asz (or bsize) aligned to addr", "sb", "", "Seek aligned to bb start", "sC", " string", "Seek to comment matching given string", "sf", "", "Seek to next function (f->addr+f->size)", "sf", " function", "Seek to address of specified function", "sg/sG", "", "Seek begin (sg) or end (sG) of section or file", "sn/sp", "", "Seek next/prev scr.nkey", "so", " [N]", "Seek to N next opcode(s)", "sr", " pc", "Seek to register", //"sp [page] seek page N (page = block)", NULL }; r_core_cmd_help(core, help_message); } break; } } else r_cons_printf ("0x%"PFMT64x"\n", core->offset); return 0; }
static int cb(RDiff *d, void *user, RDiffOp *op) { int i; //, diffmode = (int)(size_t)user; char s[256]; if (showcount) { count++; return 1; } switch (diffmode) { case 'U': // 'U' in theory never handled here case 'u': if (op->a_len > 0) { readstr (s, sizeof (s), op->a_buf, op->a_len); if (*s) { if (!quiet) printf (Color_RED); if (r_mem_is_printable ((const ut8*)s, R_MIN (strlen (s), 5))) { printf ("- %s\n", s); } else { printf ("-:"); int len = op->a_len; //R_MIN (op->a_len, strlen (op->a_buf)); for (i = 0; i < len; i++) { printf ("%02x", op->a_buf[i]); } printf (" \"%s\"\n", op->a_buf); } if (!quiet) printf (Color_RESET); } } if (op->b_len > 0) { readstr (s, sizeof (s), op->b_buf, op->b_len); if (*s) { if (!quiet) printf (Color_GREEN); if (r_mem_is_printable ((const ut8*)s, R_MIN (strlen (s), 5))) { printf ("+ %s\n", s); } else { printf ("+:"); for (i = 0; i < op->b_len; i++) { printf ("%02x", op->b_buf[i]); } printf (" \"%s\"\n", op->b_buf); } if (!quiet) printf (Color_RESET); } } break; case 'r': if (disasm) { eprintf ("r2cmds (-r) + disasm (-D) not yet implemented\n"); } if (op->a_len == op->b_len) { printf ("wx "); for (i = 0; i < op->b_len; i++) { printf ("%02x", op->b_buf[i]); } printf (" @ 0x%08"PFMT64x"\n", op->b_off); } else { if (op->a_len > 0) { printf ("r-%d @ 0x%08"PFMT64x"\n", op->a_len, op->a_off + delta); } if (op->b_len > 0) { printf ("r+%d @ 0x%08"PFMT64x"\n", op->b_len, op->b_off + delta); printf ("wx "); for (i = 0; i < op->b_len; i++) { printf ("%02x", op->b_buf[i]); } printf (" @ 0x%08"PFMT64x"\n", op->b_off+delta); } delta += (op->b_off - op->a_off); } return 1; case 'j': if (disasm) { eprintf ("JSON (-j) + disasm (-D) not yet implemented\n"); } if (json_started) { printf (",\n"); } json_started = 1; printf ("{\"offset\":%"PFMT64d",", op->a_off); printf("\"from\":\""); for (i = 0; i < op->a_len; i++) { printf ("%02x", op->a_buf[i]); } printf ("\", \"to\":\""); for (i = 0; i < op->b_len; i++) { printf ("%02x", op->b_buf[i]); } printf ("\"}"); //,\n"); return 1; case 0: default: if (disasm) { printf ("--- 0x%08"PFMT64x"\n", op->a_off); if (!core) { core = opencore (file); if (arch) { r_config_set (core->config, "asm.arch", arch); } if (bits) { r_config_set_i (core->config, "asm.bits", bits); } } if (core) { RAsmCode *ac = r_asm_mdisassemble (core->assembler, op->a_buf, op->a_len); printf ("%s\n", ac->buf_asm); //r_asm_code_free (ac); } } else { printf ("0x%08"PFMT64x" ", op->a_off); for (i = 0; i < op->a_len; i++) { printf ("%02x", op->a_buf[i]); } } if (disasm) { printf ("+++ 0x%08"PFMT64x"\n", op->b_off); if (!core) { core = opencore (NULL); } if (core) { RAsmCode *ac = r_asm_mdisassemble (core->assembler, op->b_buf, op->b_len); printf ("%s\n", ac->buf_asm); //r_asm_code_free (ac); } } else { printf (" => "); for (i = 0; i < op->b_len; i++) { printf ("%02x", op->b_buf[i]); } printf (" 0x%08"PFMT64x"\n", op->b_off); } return 1; } return 0; }
static int cmd_seek(void *data, const char *input) { RCore *core = (RCore *)data; char *cmd, *p; ut64 off; if (*input == 'r') { if (input[1] && input[2]) { if (core->io->debug) { off = r_debug_reg_get (core->dbg, input + 2); r_io_sundo_push (core->io, core->offset, r_print_get_cursor (core->print)); r_core_seek (core, off, 1); } else { RReg *orig = core->dbg->reg; core->dbg->reg = core->anal->reg; off = r_debug_reg_get (core->dbg, input + 2); core->dbg->reg = orig; r_core_seek (core, off, 1); } } else eprintf ("|Usage| 'sr PC' seek to program counter register\n"); } if (*input) { char* ptr; if ((ptr = strstr(input, "+.")) != NULL) { char* dup = strdup(input); dup[ptr - input] = '\x00'; off = r_num_math (core->num, dup + 1); core->offset = off; free (dup); } const char *inputnum = strchr (input, ' '); int sign = 1; { const char *u_num = inputnum? inputnum + 1: input + 1; off = r_num_math (core->num, u_num); if (*u_num == '-') off = -off; } #if 0 if (input[0]!='/' && inputnum && isalpha (inputnum[0]) && off == 0) { if (!r_flag_get (core->flags, inputnum)) { eprintf ("Cannot find address for '%s'\n", inputnum); return false; } } #endif if (input[0]==' ') { switch (input[1]) { case '-': sign=-1; case '+': input++; break; } } switch (*input) { case 'C': if (input[1]=='*') { r_core_cmd0 (core, "C*~^\"CC"); } else if (input[1]==' ') { typedef struct { ut64 addr; char *str; } MetaCallback; int count = 0; MetaCallback cb = { 0, NULL }; ut64 addr; char key[128]; const char *val, *comma; char *list = sdb_get (core->anal->sdb_meta, "meta.C", 0); char *str, *next, *cur = list; if (list) { for (;;) { cur = sdb_anext (cur, &next); addr = sdb_atoi (cur); snprintf (key, sizeof (key)-1, "meta.C.0x%"PFMT64x, addr); val = sdb_const_get (core->anal->sdb_meta, key, 0); if (val) { comma = strchr (val, ','); if (comma) { str = (char *)sdb_decode (comma+1, 0); if (strstr (str, input+2)) { r_cons_printf ("0x%08"PFMT64x" %s\n", addr, str); count++; cb.addr = addr; free (cb.str); cb.str = str; } else free (str); } } else eprintf ("sdb_const_get key not found '%s'\n", key); if (!next) break; cur = next; } } switch (count) { case 0: eprintf ("No matching comments\n"); break; case 1: off = cb.addr; r_io_sundo_push (core->io, core->offset, r_print_get_cursor (core->print)); r_core_seek (core, off, 1); r_core_block_read (core); break; default: eprintf ("Too many results\n"); break; } free (cb.str); } else { const char *help_msg[] = { "Usage:", "sC", "Comment grep", "sC", "*", "List all comments", "sC", " str", "Seek to the first comment matching 'str'", NULL }; r_core_cmd_help (core, help_msg); } break; case ' ': r_io_sundo_push (core->io, core->offset, r_print_get_cursor (core->print)); r_core_seek (core, off * sign, 1); r_core_block_read (core); break; case '/': { const char *pfx = r_config_get (core->config, "search.prefix"); ut64 from = r_config_get_i (core->config, "search.from"); //kwidx cfg var is ignored int kwidx = core->search->n_kws; //(int)r_config_get_i (core->config, "search.kwidx")-1; if (kwidx<0) kwidx = 0; switch (input[1]) { case ' ': case 'v': case 'V': case 'w': case 'W': case 'z': case 'm': case 'c': case 'A': case 'e': case 'E': case 'i': case 'R': case 'r': case '/': case 'x': r_config_set_i (core->config, "search.from", core->offset+1); r_config_set_i (core->config, "search.count", 1); r_core_cmdf (core, "s+1; %s; s-1; s %s%d_0; f-%s%d_0", input, pfx, kwidx, pfx, kwidx, pfx, kwidx); r_config_set_i (core->config, "search.from", from); r_config_set_i (core->config, "search.count", 0); break; case '?': eprintf ("Usage: s/.. arg.\n"); r_cons_printf ("/?\n"); break; default: eprintf ("unknown search method\n"); break; } } break; case '.': for (input++;*input=='.';input++); r_core_seek_base (core, input); break; case '*': case '=': case 'j': r_io_sundo_list (core->io, input[0]); break; case '+': if (input[1]!='\0') { int delta = (input[1]=='+')? core->blocksize: off; r_io_sundo_push (core->io, core->offset, r_print_get_cursor (core->print)); r_core_seek_delta (core, delta); } else { RIOUndos *undo = r_io_sundo_redo (core->io); if (undo != NULL) r_core_seek (core, undo->off, 0); } break; case '-': if (input[1]!='\0') { int delta = (input[1]=='-') ? -core->blocksize: -off; r_io_sundo_push (core->io, core->offset, r_print_get_cursor (core->print)); r_core_seek_delta (core, delta); } else { RIOUndos *undo = r_io_sundo (core->io, core->offset); if (undo) { r_core_seek (core, undo->off, 0); r_core_block_read (core); } } break; case 'n': r_io_sundo_push (core->io, core->offset, r_print_get_cursor (core->print)); r_core_seek_next (core, r_config_get (core->config, "scr.nkey")); break; case 'p': r_io_sundo_push (core->io, core->offset, r_print_get_cursor (core->print)); r_core_seek_previous (core, r_config_get (core->config, "scr.nkey")); break; case 'a': off = core->blocksize; if (input[1]&&input[2]) { cmd = strdup (input); p = strchr (cmd+2, ' '); if (p) { off = r_num_math (core->num, p+1);; *p = '\0'; } cmd[0] = 's'; // perform real seek if provided r_cmd_call (core->rcmd, cmd); free (cmd); } r_io_sundo_push (core->io, core->offset, r_print_get_cursor (core->print)); r_core_seek_align (core, off, 0); break; case 'b': if (off == 0) off = core->offset; r_io_sundo_push (core->io, core->offset, r_print_get_cursor (core->print)); r_core_anal_bb_seek (core, off); break; case 'f': // "sf" if (strlen(input) > 2 && input[1]==' ') { RAnalFunction *fcn = r_anal_fcn_find_name (core->anal, input+2); if (fcn) { r_core_seek (core, fcn->addr, 1); } break; } RAnalFunction *fcn = r_anal_get_fcn_in (core->anal, core->offset, 0); if (fcn) { r_core_seek (core, fcn->addr + r_anal_fcn_size (fcn), 1); } break; case 'o': // "so" { RAnalOp op; int val=0, ret, i, n = r_num_math (core->num, input+1); if (n==0) n = 1; if (n<0) { int instr_len; ut64 addr = core->offset; int numinstr = n * -1; if (r_core_prevop_addr (core, core->offset, numinstr, &addr)) { ret = core->offset - addr; } else { ret = r_core_asm_bwdis_len (core, &instr_len, &addr, numinstr); } r_core_seek (core, addr, true); val += ret; } else { for (val=i=0; i<n; i++) { ret = r_anal_op (core->anal, &op, core->offset, core->block, core->blocksize); if (ret<1) ret = 1; r_core_seek_delta (core, ret); val += ret; } } core->num->value = val; } break; case 'g': // "sg" { RIOSection *s = r_io_section_vget (core->io, core->offset); if (s) r_core_seek (core, s->vaddr, 1); else r_core_seek (core, 0, 1); } break; case 'G': // "sG" { if (!core->file) break; RIOSection *s = r_io_section_vget (core->io, core->offset); // XXX: this +2 is a hack. must fix gap between sections if (s) r_core_seek (core, s->vaddr+s->size+2, 1); else r_core_seek (core, r_io_desc_size (core->io, core->file->desc), 1); } break; case 'l': // "sl" { int sl_arg = r_num_math (core->num, input+1); const char *help_msg[] = { "Usage:", "sl+ or sl- or slc", "", "sl", " [line]", "Seek to absolute line", "sl", "[+-][line]", "Seek to relative line", "slc", "", "Clear line cache", "sll", "", "Show total number of lines", NULL }; switch (input[1]) { case 0: if (!core->print->lines_cache) { __init_seek_line (core); } __get_current_line (core); break; case ' ': if (!core->print->lines_cache) { __init_seek_line (core); } __seek_line_absolute (core, sl_arg); break; case '+': case '-': if (!core->print->lines_cache) { __init_seek_line (core); } __seek_line_relative (core, sl_arg); break; case 'c': __clean_lines_cache (core); break; case 'l': if (!core->print->lines_cache) { __init_seek_line (core); } eprintf ("%d lines\n", core->print->lines_cache_sz-1); break; case '?': r_core_cmd_help (core, help_msg); break; } } break; case ':': printPadded (core, atoi (input + 1)); break; case '?': { const char * help_message[] = { "Usage: s", "", " # Seek commands", "s", "", "Print current address", "s:", "pad", "Print current address with N padded zeros (defaults to 8)", "s", " addr", "Seek to address", "s-", "", "Undo seek", "s-", " n", "Seek n bytes backward", "s--", "", "Seek blocksize bytes backward", "s+", "", "Redo seek", "s+", " n", "Seek n bytes forward", "s++", "", "Seek blocksize bytes forward", "s[j*=]", "", "List undo seek history (JSON, =list, *r2)", "s/", " DATA", "Search for next occurrence of 'DATA'", "s/x", " 9091", "Search for next occurrence of \\x90\\x91", "s.", "hexoff", "Seek honoring a base from core->offset", "sa", " [[+-]a] [asz]", "Seek asz (or bsize) aligned to addr", "sb", "", "Seek aligned to bb start", "sC", "[?] string", "Seek to comment matching given string", "sf", "", "Seek to next function (f->addr+f->size)", "sf", " function", "Seek to address of specified function", "sg/sG", "", "Seek begin (sg) or end (sG) of section or file", "sl", "[?] [+-]line", "Seek to line", "sn/sp", "", "Seek next/prev scr.nkey", "so", " [N]", "Seek to N next opcode(s)", "sr", " pc", "Seek to register", //"sp [page] seek page N (page = block)", NULL }; r_core_cmd_help(core, help_message); } break; } } else r_cons_printf ("0x%"PFMT64x"\n", core->offset); return 0; }
R_API int r_core_rtr_http(RCore *core, int launch, const char *path) { char buf[32]; RSocketHTTPRequest *rs; int iport, oldsandbox = -1; int timeout = r_config_get_i (core->config, "http.timeout"); int x = r_config_get_i (core->config, "scr.html"); int y = r_config_get_i (core->config, "scr.color"); int z = r_config_get_i (core->config, "asm.bytes"); int u = r_config_get_i (core->config, "scr.interactive"); int v = r_config_get_i (core->config, "asm.cmtright"); const char *port = r_config_get (core->config, "http.port"); char *allow = (char *)r_config_get (core->config, "http.allow"); if (core->http_up) { eprintf ("http server is already running\n"); return 1; } if (r_sandbox_enable (0)) { eprintf ("sandbox: connect disabled\n"); return 1; } if (path && atoi (path)) { port = path; path = NULL; } if (!strcmp (port, "0")) { r_num_irand (); iport = 1024+r_num_rand (45256); snprintf (buf, sizeof (buf), "%d", iport); port = buf; } s = r_socket_new (R_FALSE); s->local = !r_config_get_i (core->config, "http.public"); if (!r_socket_listen (s, port, NULL)) { eprintf ("Cannot listen on http.port\n"); return 1; } if (launch) { char cmd[128]; const char *browser = r_config_get (core->config, "http.browser"); snprintf (cmd, sizeof (cmd)-1, "%s http://localhost:%d/%s &", browser, atoi (port), path?path:""); r_sys_cmd (cmd); } r_config_set (core->config, "asm.cmtright", "false"); r_config_set (core->config, "scr.html", "true"); r_config_set (core->config, "scr.color", "false"); r_config_set (core->config, "asm.bytes", "false"); r_config_set (core->config, "scr.interactive", "false"); if (r_config_get_i (core->config, "http.sandbox")) { oldsandbox = r_config_get_i (core->config, "cfg.sandbox"); r_config_set (core->config, "cfg.sandbox", "true"); } eprintf ("Starting http server...\n"); eprintf ("http://localhost:%d/\n", atoi (port)); core->http_up = R_TRUE; while (!r_cons_singleton ()->breaked) { r_cons_break ((RConsBreak)http_break, core); rs = r_socket_http_accept (s, timeout); if (!rs) { if (!s) break; r_sys_usleep (100); continue; } if (allow && *allow) { int accepted = R_FALSE; const char *host; char *p, *peer = r_socket_to_string (rs->s); char *allows = strdup (allow); //eprintf ("Firewall (%s)\n", allows); int i, count = r_str_split (allows, ','); p = strchr (peer, ':'); if (p) *p = 0; for (i=0; i<count; i++) { host = r_str_word_get0 (allows, i); //eprintf ("--- (%s) (%s)\n", host, peer); if (!strcmp (host, peer)) { accepted = R_TRUE; break; } } free (peer); free (allows); if (!accepted) { r_socket_http_close (rs); continue; } } if (!rs->method || !rs->path) { eprintf ("Invalid http headers received from client\n"); r_socket_http_close (rs); continue; } char *dir = NULL; if (r_config_get_i (core->config, "http.dirlist")) if (r_file_is_directory (rs->path)) dir = strdup (rs->path); if (!strcmp (rs->method, "GET")) { if (!memcmp (rs->path, "/up", 3)) { if (r_config_get_i (core->config, "http.upget")) { const char *uproot = r_config_get (core->config, "http.uproot"); if (!rs->path[3] || (rs->path[3]=='/'&&!rs->path[4])) { char *ptr = rtr_dir_files (uproot); r_socket_http_response (rs, 200, ptr, 0, NULL); free (ptr); } else { char *path = r_file_root (uproot, rs->path + 4); if (r_file_exists (path)) { int sz = 0; char *f = r_file_slurp (path, &sz); if (f) { r_socket_http_response (rs, 200, f, sz, NULL); free (f); } else { r_socket_http_response (rs, 403, "Permission denied", 0, NULL); eprintf ("http: Cannot open '%s'\n", path); } } else { if (dir) { char *resp = rtr_dir_files (dir); r_socket_http_response (rs, 404, resp, 0, NULL); free (resp); } else { eprintf ("File '%s' not found\n", path); r_socket_http_response (rs, 404, "File not found\n", 0, NULL); } } free (path); } } else { r_socket_http_response (rs, 403, "Permission denied\n", 0, NULL); } } else if (!memcmp (rs->path, "/cmd/", 5)) { char *cmd = rs->path +5; char foo[32]; const char *httpcmd = r_config_get (core->config, "http.uri"); while (*cmd=='/') cmd++; if (httpcmd && *httpcmd) { int len; char *res; // do remote http query and proxy response snprintf (foo, sizeof (foo), "%s/%s", httpcmd, cmd); res = r_socket_http_get (foo, NULL, &len); if (res) { res[len]=0; r_cons_printf ("%s\n", res); } } else { char *out, *cmd = rs->path+5; r_str_uri_decode (cmd); // eprintf ("CMD (%s)\n", cmd); out = r_core_cmd_str_pipe (core, cmd); // eprintf ("\nOUT LEN = %d\n", strlen (out)); if (out) { char *res = r_str_uri_encode (out); r_socket_http_response (rs, 200, out, 0, "Content-Type: text/plain\n"); free (out); free (res); } else r_socket_http_response (rs, 200, "", 0, NULL); } } else { const char *root = r_config_get (core->config, "http.root"); char *path = r_file_root (root, rs->path); // FD IS OK HERE if (rs->path [strlen (rs->path)-1] == '/') { path = r_str_concat (path, "index.html"); //rs->path = r_str_concat (rs->path, "index.html"); } else { //snprintf (path, sizeof (path), "%s/%s", root, rs->path); if (r_file_is_directory (path)) { char res[128]; snprintf (res, sizeof (res), "Location: %s/\n", rs->path); r_socket_http_response (rs, 302, NULL, 0, res); r_socket_http_close (rs); free (path); free (dir); dir = NULL; continue; } } if (r_file_exists (path)) { int sz = 0; char *f = r_file_slurp (path, &sz); if (f) { const char *contenttype = NULL; if (strstr (path, ".js")) contenttype = "Content-Type: application/javascript\n"; if (strstr (path, ".css")) contenttype = "Content-Type: text/css\n"; if (strstr (path, ".html")) contenttype = "Content-Type: text/html\n"; r_socket_http_response (rs, 200, f, sz, contenttype); free (f); } else { r_socket_http_response (rs, 403, "Permission denied", 0, NULL); eprintf ("http: Cannot open '%s'\n", path); } } else { if (dir) { char *resp = rtr_dir_files (dir); eprintf ("Dirlisting %s\n", dir); r_socket_http_response (rs, 404, resp, 0, NULL); free (resp); } else { eprintf ("File '%s' not found\n", path); r_socket_http_response (rs, 404, "File not found\n", 0, NULL); } } free (path); } } else if (!strcmp (rs->method, "POST")) { ut8 *ret; int retlen; char buf[128]; if (r_config_get_i (core->config, "http.upload")) { ret = r_socket_http_handle_upload ( rs->data, rs->data_length, &retlen); if (ret) { ut64 size = r_config_get_i (core->config, "http.maxsize"); if (size && retlen > size) { r_socket_http_response (rs, 403, "403 File too big\n", 0, NULL); } else { char *filename = r_file_root ( r_config_get (core->config, "http.uproot"), rs->path + 4); eprintf ("UPLOADED '%s'\n", filename); r_file_dump (filename, ret, retlen); free (filename); snprintf (buf, sizeof (buf), "<html><body><h2>uploaded %d bytes. Thanks</h2>\n", retlen); r_socket_http_response (rs, 200, buf, 0, NULL); } free (ret); } } else { r_socket_http_response (rs, 403, "403 Forbidden\n", 0, NULL); } } else { r_socket_http_response (rs, 404, "Invalid protocol", 0, NULL); } r_socket_http_close (rs); free (dir); } core->http_up = R_FALSE; r_socket_free (s); r_cons_break_end (); r_config_set_i (core->config, "scr.html", x); r_config_set_i (core->config, "scr.color", y); r_config_set_i (core->config, "asm.bytes", z); r_config_set_i (core->config, "scr.interactive", u); r_config_set_i (core->config, "asm.cmtright", v); if (oldsandbox != -1) r_config_set_i (core->config, "cfg.sandbox", oldsandbox); return 0; }
static int cb(RDiff *d, void *user, RDiffOp *op) { int i; //, diffmode = (int)(size_t)user; if (showcount) { count++; return 1; } switch (diffmode) { case 'r': if (disasm) { eprintf ("r2cmds (-r) + disasm (-D) not yet implemented\n"); } if (op->a_len == op->b_len) { printf ("wx "); for (i=0; i<op->b_len; i++) printf ("%02x", op->b_buf[i]); printf (" @ 0x%08"PFMT64x"\n", op->b_off); } else { if ((op->a_len)>0) printf ("r-%d @ 0x%08"PFMT64x"\n", op->a_len, op->a_off+delta); if (op->b_len> 0) { printf ("r+%d @ 0x%08"PFMT64x"\n", op->b_len, op->b_off+delta); printf ("wx "); for (i=0; i<op->b_len; i++) printf ("%02x", op->b_buf[i]); printf (" @ 0x%08"PFMT64x"\n", op->b_off+delta); } delta += (op->b_off - op->a_off); } return 1; case 'j': if (disasm) { eprintf ("JSON (-j) + disasm (-D) not yet implemented\n"); } if (json_started) printf(",\n"); json_started = 1; printf ("{\"offset\":%"PFMT64d",", op->a_off); printf("\"from\":\""); for (i = 0;i<op->a_len;i++) printf ("%02x", op->a_buf[i]); printf ("\", \"to\":\""); for (i=0; i<op->b_len; i++) printf ("%02x", op->b_buf[i]); printf ("\"}"); //,\n"); return 1; case 0: default: if (disasm) { printf ("--- 0x%08"PFMT64x"\n", op->a_off); if (!core) { core = opencore (file); if (arch) { r_config_set (core->config, "asm.arch", arch); } if (bits) { r_config_set_i (core->config, "asm.bits", bits); } } if (core) { RAsmCode *ac = r_asm_mdisassemble (core->assembler, op->a_buf, op->a_len); printf ("%s\n", ac->buf_asm); //r_asm_code_free (ac); } } else { printf ("0x%08"PFMT64x" ", op->a_off); for (i = 0; i < op->a_len; i++) printf ("%02x", op->a_buf[i]); } if (disasm) { printf ("+++ 0x%08"PFMT64x"\n", op->b_off); if (!core) { core = opencore (NULL); } if (core) { RAsmCode *ac = r_asm_mdisassemble (core->assembler, op->b_buf, op->b_len); printf ("%s\n", ac->buf_asm); //r_asm_code_free (ac); } } else { printf (" => "); for (i=0; i < op->b_len; i++) printf ("%02x", op->b_buf[i]); printf (" 0x%08"PFMT64x"\n", op->b_off); } return 1; } }
static int cmd_seek(void *data, const char *input) { RCore *core = (RCore *) data; char *cmd, *p; ut64 off; if (!*input) { r_cons_printf ("0x%"PFMT64x "\n", core->offset); return 0; } char *ptr; if ((ptr = strstr (input, "+.")) != NULL) { char *dup = strdup (input); dup[ptr - input] = '\x00'; off = r_num_math (core->num, dup + 1); core->offset = off; free (dup); } const char *inputnum = strchr (input, ' '); { const char *u_num = inputnum? inputnum + 1: input + 1; off = r_num_math (core->num, u_num); if (*u_num == '-') { off = -off; } } int sign = 1; if (input[0] == ' ') { switch (input[1]) { case '-': sign = -1; /* pass thru */ case '+': input++; break; } } bool silent = false; if (*input == 's') { silent = true; input++; if (*input == '?') { const char *help_message[] = { "Usage: ss", "", " # Seek silently (not recorded in the seek history)", "s?", "", "Works with all s subcommands", NULL }; r_core_cmd_help (core, help_message); return 0; } } switch (*input) { case 'r': if (input[1] && input[2]) { seek_to_register (core, input + 2, silent); } else { eprintf ("|Usage| 'sr PC' seek to program counter register\n"); } break; case 'C': if (input[1] == '*') { r_core_cmd0 (core, "C*~^\"CC"); } else if (input[1] == ' ') { typedef struct { ut64 addr; char *str; } MetaCallback; int count = 0; MetaCallback cb = { 0, NULL }; ut64 addr; char key[128]; const char *val, *comma; char *list = sdb_get (core->anal->sdb_meta, "meta.C", 0); char *str, *next, *cur = list; if (list) { for (;;) { cur = sdb_anext (cur, &next); addr = sdb_atoi (cur); snprintf (key, sizeof (key) - 1, "meta.C.0x%"PFMT64x, addr); val = sdb_const_get (core->anal->sdb_meta, key, 0); if (val) { comma = strchr (val, ','); if (comma) { str = (char *) sdb_decode (comma + 1, 0); if (strstr (str, input + 2)) { r_cons_printf ("0x%08"PFMT64x " %s\n", addr, str); count++; cb.addr = addr; free (cb.str); cb.str = str; } else { free (str); } } } else { eprintf ("sdb_const_get key not found '%s'\n", key); } if (!next) { break; } cur = next; } } switch (count) { case 0: eprintf ("No matching comments\n"); break; case 1: off = cb.addr; if (!silent) { r_io_sundo_push (core->io, core->offset, r_print_get_cursor (core->print)); } r_core_seek (core, off, 1); r_core_block_read (core); break; default: eprintf ("Too many results\n"); break; } free (cb.str); } else { const char *help_msg[] = { "Usage:", "sC", "Comment grep", "sC", "*", "List all comments", "sC", " str", "Seek to the first comment matching 'str'", NULL }; r_core_cmd_help (core, help_msg); } break; case ' ': if (!silent) { r_io_sundo_push (core->io, core->offset, r_print_get_cursor (core->print)); } r_core_seek (core, off * sign, 1); r_core_block_read (core); break; case '/': { const char *pfx = r_config_get (core->config, "search.prefix"); ut64 from = r_config_get_i (core->config, "search.from"); // kwidx cfg var is ignored int kwidx = core->search->n_kws; // (int)r_config_get_i (core->config, "search.kwidx")-1; if (kwidx < 0) { kwidx = 0; } switch (input[1]) { case ' ': case 'v': case 'V': case 'w': case 'W': case 'z': case 'm': case 'c': case 'A': case 'e': case 'E': case 'i': case 'R': case 'r': case '/': case 'x': r_config_set_i (core->config, "search.from", core->offset + 1); r_config_set_i (core->config, "search.count", 1); r_core_cmdf (core, "s+1; %s; s-1; s %s%d_0; f-%s%d_0", input, pfx, kwidx, pfx, kwidx, pfx, kwidx); r_config_set_i (core->config, "search.from", from); r_config_set_i (core->config, "search.count", 0); break; case '?': eprintf ("Usage: s/.. arg.\n"); r_cons_printf ("/?\n"); break; default: eprintf ("unknown search method\n"); break; } } break; case '.': for (input++; *input == '.'; input++) { ; } r_core_seek_base (core, input); break; case 'j': // sj { RList /*<ut64 *>*/ *addrs = r_list_newf (free); RList /*<char *>*/ *names = r_list_newf (free); RList *list = r_io_sundo_list (core->io, '!'); ut64 lsz = 0; ut64 i; RListIter *iter; RIOUndos *undo; if (list) { r_list_foreach (list, iter, undo) { char *name = NULL; core->flags->space_strict = true; RFlagItem *f = r_flag_get_at (core->flags, undo->off, true); core->flags->space_strict = false; if (f) { if (f->offset != undo->off) { name = r_str_newf ("%s + %d\n", f->name, (int)(undo->off- f->offset)); } else { name = strdup (f->name); } } if (!name) { name = strdup (""); } ut64 *val = malloc (sizeof (ut64)); if (!val) { free (name); break; } *val = undo->off; r_list_append (addrs, val); r_list_append (names, strdup (name)); lsz++; free (name); } r_list_free (list); } r_cons_printf ("["); for (i = 0; i < lsz; ++i) { ut64 *addr = r_list_get_n (addrs, i); const char *name = r_list_get_n (names, i); // XXX(should the "name" field be optional? That might make // a bit more sense. r_cons_printf ("{\"offset\":%"PFMT64d",\"symbol\":\"%s\"}", *addr, name); if (i != lsz - 1) { r_cons_printf (","); } } r_cons_printf ("]\n"); r_list_free (addrs); r_list_free (names); } break; case '*': case '=': case '!': { RList *list = r_io_sundo_list (core->io, input[0]); RListIter *iter; RIOUndos *undo; if (list) { r_list_foreach (list, iter, undo) { char *name = NULL; core->flags->space_strict = true; RFlagItem *f = r_flag_get_at (core->flags, undo->off, true); core->flags->space_strict = false; if (f) { if (f->offset != undo->off) { name = r_str_newf ("%s + %d\n", f->name, (int)(undo->off- f->offset)); } else { name = strdup (f->name); } } if (!name) { name = strdup (""); } r_cons_printf ("0x%"PFMT64x" %s\n", undo->off, name); free (name); } r_list_free (list); } }
R_API int r_core_visual_cmd(RCore *core, int ch) { RAsmOp op; char buf[4096]; int i, ret, offscreen, cols = core->print->cols; ch = r_cons_arrow_to_hjkl (ch); ch = visual_nkey (core, ch); if (ch<2) return 1; // do we need hotkeys for data references? not only calls? if (ch>='0'&& ch<='9') { r_io_sundo_push (core->io, core->offset); r_core_seek (core, core->asmqjmps[ch-'0'], 1); r_core_block_read (core, 1); } else switch (ch) { case 9: // tab { // XXX: unify diff mode detection ut64 f = r_config_get_i (core->config, "diff.from"); ut64 t = r_config_get_i (core->config, "diff.to"); if (f == t && f == 0) { core->print->col = core->print->col==1? 2: 1; } else { ut64 delta = core->offset - f; r_core_seek (core, t+delta, 1); r_config_set_i (core->config, "diff.from", t); r_config_set_i (core->config, "diff.to", f); } } break; case 'c': // XXX dupped flag imho setcursor (core, curset ^ 1); break; case 'd': r_core_visual_define (core); break; case 'D': setdiff (core); break; case 'C': color ^= 1; if (color) flags |= R_PRINT_FLAGS_COLOR; else flags &= ~(flags&R_PRINT_FLAGS_COLOR); r_config_set_i (core->config, "scr.color", color); r_print_set_flags (core->print, flags); break; case 'f': { int range; char name[256], *n; r_line_set_prompt ("flag name: "); if (r_cons_fgets (name, sizeof (name), 0, NULL) >=0 && *name) { n = r_str_chop (name); if (*name=='-') { if (*n) r_flag_unset (core->flags, n+1, NULL); } else { range = curset? (R_ABS (cursor-ocursor)+1): 1; if (range<1) range = 1; if (*n) r_flag_set (core->flags, n, core->offset + cursor, range, 1); } } } break; case 'F': r_flag_unset_i (core->flags, core->offset + cursor, NULL); break; case 'n': r_core_seek_next (core, r_config_get (core->config, "scr.nkey")); break; case 'N': r_core_seek_previous (core, r_config_get (core->config, "scr.nkey")); break; case 'A': { int oc = curset; ut64 off = curset? core->offset+cursor : core->offset; curset = 0; r_core_visual_asm (core, off); curset = oc; } break; case 'a': if (core->file && !(core->file->rwx & 2)) { r_cons_printf ("\nFile has been opened in read-only mode. Use -w flag\n"); r_cons_any_key (); return R_TRUE; } r_cons_printf ("Enter assembler opcodes separated with ';':\n"); r_cons_show_cursor (R_TRUE); r_cons_flush (); r_cons_set_raw (R_FALSE); strcpy (buf, "wa "); r_line_set_prompt (":> "); if (r_cons_fgets (buf+3, 1000, 0, NULL) <0) buf[0]='\0'; if (*buf) { if (curset) r_core_seek (core, core->offset + cursor, 0); r_core_cmd (core, buf, R_TRUE); if (curset) r_core_seek (core, core->offset - cursor, 1); } r_cons_show_cursor (R_FALSE); r_cons_set_raw (R_TRUE); break; case 'i': case 'I': if (core->file && !(core->file->rwx & 2)) { r_cons_printf ("\nFile has been opened in read-only mode. Use -w flag\n"); r_cons_any_key (); return R_TRUE; } r_cons_show_cursor (R_TRUE); r_cons_flush (); r_cons_set_raw (0); if (ch=='I') { strcpy (buf, "wow "); r_line_set_prompt ("insert hexpair block: "); if (r_cons_fgets (buf+4, sizeof (buf)-3, 0, NULL) <0) buf[0]='\0'; char *p = strdup (buf); int cur = core->print->cur; if (cur>=core->blocksize) cur = core->print->cur-1; snprintf (buf, sizeof (buf), "%s @ $$0!%i", p, core->blocksize-cursor); r_core_cmd (core, buf, 0); free (p); break; } if (core->print->col==2) { strcpy (buf, "w "); r_line_set_prompt ("insert string: "); if (r_cons_fgets (buf+2, sizeof (buf)-3, 0, NULL) <0) buf[0]='\0'; } else { strcpy (buf, "wx "); r_line_set_prompt ("insert hex: "); if (r_cons_fgets (buf+3, sizeof (buf)-4, 0, NULL) <0) buf[0]='\0'; } if (curset) r_core_seek (core, core->offset + cursor, 0); r_core_cmd (core, buf, 1); if (curset) r_core_seek (core, core->offset - cursor, 1); r_cons_set_raw (1); r_cons_show_cursor (R_FALSE); break; case 'e': r_core_visual_config (core); break; case 'M': r_core_visual_mounts (core); break; case 't': r_core_visual_trackflags (core); break; case 'x': { int count = 0; RList *xrefs = NULL; RAnalRef *refi; RListIter *iter; RAnalFunction *fun; if ((xrefs = r_anal_xref_get (core->anal, core->offset))) { r_cons_printf ("XREFS:\n"); if (r_list_empty (xrefs)) { r_cons_printf ("\tNo XREF found at 0x%"PFMT64x"\n", core->offset); r_cons_any_key (); r_cons_clear00 (); } else { r_list_foreach (xrefs, iter, refi) { fun = r_anal_fcn_find (core->anal, refi->addr, R_ANAL_FCN_TYPE_NULL); r_cons_printf ("\t[%i] %s XREF 0x%08"PFMT64x" (%s)\n", count, refi->type==R_ANAL_REF_TYPE_CODE?"CODE (JMP)": refi->type==R_ANAL_REF_TYPE_CALL?"CODE (CALL)":"DATA", refi->addr, fun?fun->name:"unk"); if (++count > 9) break; } } } else xrefs = NULL;
R_API int r_core_pseudo_code(RCore *core, const char *input) { Sdb *db; ut64 queuegoto = 0LL; const char *blocktype = "else"; RAnalFunction *fcn = r_anal_get_fcn_in (core->anal, core->offset, R_ANAL_FCN_TYPE_NULL); RConfigHold *hc = r_config_hold_new (core->config); if (!hc) { return false; } r_config_save_num (hc, "asm.pseudo", "asm.decode", "asm.lines", "asm.bytes", NULL); r_config_save_num (hc, "asm.offset", "asm.flags", "asm.fcnlines", "asm.comments", NULL); r_config_save_num (hc, "asm.functions", "asm.section", "asm.cmtcol", "asm.filter", NULL); r_config_save_num (hc, "scr.color", "asm.emustr", "asm.emu", "asm.emuwrite", NULL); if (!fcn) { eprintf ("Cannot find function in 0x%08"PFMT64x"\n", core->offset); r_config_hold_free (hc); return false; } r_config_set_i (core->config, "scr.color", 0); r_config_set_i (core->config, "asm.pseudo", 1); r_config_set_i (core->config, "asm.decode", 0); r_config_set_i (core->config, "asm.filter", 1); r_config_set_i (core->config, "asm.lines", 0); r_config_set_i (core->config, "asm.bytes", 0); r_config_set_i (core->config, "asm.offset", 0); r_config_set_i (core->config, "asm.flags", 0); r_config_set_i (core->config, "asm.emu", 1); r_config_set_i (core->config, "asm.emustr", 1); r_config_set_i (core->config, "asm.emuwrite", 1); r_config_set_i (core->config, "asm.fcnlines", 0); r_config_set_i (core->config, "asm.comments", 1); r_config_set_i (core->config, "asm.functions", 0); r_config_set_i (core->config, "asm.tabs", 0); r_config_set_i (core->config, "asm.section", 0); r_config_set_i (core->config, "asm.cmtcol", 30); r_core_cmd0 (core, "aeim"); db = sdb_new0 (); /* */ // walk all basic blocks // define depth level for each block // use it for indentation // asm.pseudo=true // asm.decode=true RAnalBlock *bb = r_list_first (fcn->bbs); char indentstr[1024]; int n_bb = r_list_length (fcn->bbs); r_cons_printf ("function %s () {", fcn->name); int indent = 1; int nindent = 1; do { #define I_TAB 4 #define K_MARK(x) sdb_fmt(0,"mark.%"PFMT64x,x) #define K_ELSE(x) sdb_fmt(0,"else.%"PFMT64x,x) #define K_INDENT(x) sdb_fmt(0,"loc.%"PFMT64x,x) #define SET_INDENT(x) { memset (indentstr, ' ', x*I_TAB); indentstr [(x*I_TAB)-2] = 0; } if (!bb) break; r_cons_push (); char *code = r_core_cmd_str (core, sdb_fmt (0, "pD %d @ 0x%08"PFMT64x"\n", bb->size, bb->addr)); r_cons_pop (); memset (indentstr, ' ', indent * I_TAB); indentstr [(indent * I_TAB) - 2] = 0; code = r_str_prefix_all (code, indentstr); int len = strlen (code); code[len - 1] = 0; // chop last newline //r_cons_printf ("\n%s loc_0x%llx:\n", indentstr, bb->addr); //if (nindent != indent) { // r_cons_printf ("\n%s loc_0x%llx:\n", indentstr, bb->addr); //} find_and_change (code, len); if (!sdb_const_get (db, K_MARK (bb->addr), 0)) { bool mustprint = !queuegoto || queuegoto != bb->addr; if (mustprint) { if (queuegoto) { r_cons_printf ("\n%s goto loc_0x%llx", indentstr, queuegoto); queuegoto = 0LL; } r_cons_printf ("\n%s loc_0x%llx:\n", indentstr, bb->addr); indentstr[(indent * I_TAB) - 2] = 0; r_cons_printf ("\n%s", code); free (code); sdb_num_set (db, K_MARK (bb->addr), 1, 0); } } if (sdb_const_get (db, K_INDENT (bb->addr), 0)) { // already analyzed, go pop and continue // XXX check if cant pop //eprintf ("%s// 0x%08llx already analyzed\n", indentstr, bb->addr); ut64 addr = sdb_array_pop_num (db, "indent", NULL); if (addr == UT64_MAX) { int i; nindent = 1; for (i = indent; i != nindent; i--) { SET_INDENT (i); r_cons_printf ("\n%s}", indentstr); } r_cons_printf ("\n%sreturn;\n", indentstr); break; } if (sdb_num_get (db, K_ELSE (bb->addr), 0)) { if (!strcmp (blocktype, "else")) { r_cons_printf ("\n%s } %s {", indentstr, blocktype); } else { r_cons_printf ("\n%s } %s (?);", indentstr, blocktype); } } else { r_cons_printf ("\n%s}", indentstr); } if (addr != bb->addr) { queuegoto = addr; //r_cons_printf ("\n%s goto loc_0x%llx", indentstr, addr); } bb = r_anal_bb_from_offset (core->anal, addr); if (!bb) { eprintf ("failed block\n"); break; } //eprintf ("next is %llx\n", addr); nindent = sdb_num_get (db, K_INDENT (addr), NULL); if (indent > nindent && !strcmp (blocktype, "else")) { int i; for (i = indent; i != nindent; i--) { SET_INDENT (i); r_cons_printf ("\n%s }", indentstr); } } indent = nindent; } else { sdb_set (db, K_INDENT (bb->addr), "passed", 0); if (bb->jump != UT64_MAX) { int swap = 1; // TODO: determine which branch take first ut64 jump = swap ? bb->jump : bb->fail; ut64 fail = swap ? bb->fail : bb->jump; // if its from another function chop it! RAnalFunction *curfcn = r_anal_get_fcn_in (core->anal, jump, R_ANAL_FCN_TYPE_NULL); if (curfcn != fcn) { // chop that branch r_cons_printf ("\n // chop\n"); break; } if (sdb_get (db, K_INDENT (jump), 0)) { // already tracekd if (!sdb_get (db, K_INDENT (fail), 0)) { bb = r_anal_bb_from_offset (core->anal, fail); } } else { bb = r_anal_bb_from_offset (core->anal, jump); if (!bb) { eprintf ("failed to retrieve blcok at 0x%"PFMT64x"\n", jump); break; } if (fail != UT64_MAX) { // do not push if already pushed indent++; if (sdb_get (db, K_INDENT (bb->fail), 0)) { /* do nothing here */ eprintf ("BlockAlready 0x%"PFMT64x"\n", bb->addr); } else { // r_cons_printf (" { RADICAL %llx\n", bb->addr); sdb_array_push_num (db, "indent", fail, 0); sdb_num_set (db, K_INDENT (fail), indent, 0); sdb_num_set (db, K_ELSE (fail), 1, 0); SET_INDENT (indent); r_cons_printf ("\n%s {", indentstr); } } else { r_cons_printf ("\n%s do", indentstr); sdb_array_push_num (db, "indent", jump, 0); sdb_num_set (db, K_INDENT (jump), indent, 0); sdb_num_set (db, K_ELSE (jump), 1, 0); if (jump <= bb->addr) { blocktype = "while"; } else { blocktype = "else"; } r_cons_printf ("\n%s {", indentstr); indent++; } } } else { ut64 addr = sdb_array_pop_num (db, "indent", NULL); if (addr == UT64_MAX) { //r_cons_printf ("\nbreak\n"); break; } bb = r_anal_bb_from_offset (core->anal, addr); nindent = sdb_num_get (db, K_INDENT (addr), NULL); if (indent > nindent) { int i; for (i = indent; i != nindent; i--) { SET_INDENT (i); r_cons_printf ("\n%s}", indentstr); } } if (nindent != indent) { r_cons_printf ("\n%s} else {\n", indentstr); } indent = nindent; } } //n_bb --; } while (n_bb > 0); r_cons_printf ("\n}\n"); r_config_restore (hc); r_config_hold_free (hc); sdb_free (db); return true; }
static int cmd_cmp(void *data, const char *input) { RCore *core = data; FILE *fd; ut8 *buf; int ret; ut32 v32; ut64 v64; switch (*input) { case ' ': radare_compare (core, core->block, (ut8*)input+1, strlen (input+1)+1); break; case 'x': if (input[1]!=' ') { eprintf ("Usage: cx 001122'\n"); return 0; } buf = (ut8*)malloc (strlen (input+2)); ret = r_hex_str2bin (input+2, buf); if (ret<1) eprintf ("Cannot parse hexpair\n"); else radare_compare (core, core->block, buf, ret); free (buf); break; case 'X': buf = malloc (core->blocksize); ret = r_io_read_at (core->io, r_num_math (core->num, input+1), buf, core->blocksize); radare_compare (core, core->block, buf, ret); free (buf); break; case 'f': if (input[1]!=' ') { eprintf ("Please. use 'cf [file]'\n"); return 0; } fd = fopen (input+2, "rb"); if (fd == NULL) { eprintf ("Cannot open file '%s'\n", input+2); return 0; } buf = (ut8 *)malloc (core->blocksize); fread (buf, 1, core->blocksize, fd); fclose (fd); radare_compare (core, core->block, buf, core->blocksize); free (buf); break; case 'q': v64 = (ut64) r_num_math (core->num, input+1); radare_compare (core, core->block, (ut8*)&v64, sizeof (v64)); break; case 'd': v32 = (ut32) r_num_math (core->num, input+1); radare_compare (core, core->block, (ut8*)&v32, sizeof (v32)); break; #if 0 case 'c': radare_compare_code ( r_num_math (core->num, input+1), core->block, core->blocksize); break; case 'D': { // XXX ugly hack char cmd[1024]; sprintf (cmd, "radiff -b %s %s", ".curblock", input+2); r_file_dump (".curblock", config.block, config.block_size); radare_system(cmd); unlink(".curblock"); } break; #endif case 'g': { // XXX: this is broken int diffops = 0; RCore *core2; char *file2 = NULL; if (input[1]=='o') { file2 = (char*)r_str_chop_ro (input+2); r_anal_diff_setup (core->anal, R_TRUE, -1, -1); } else if (input[1]==' ') { file2 = (char*)r_str_chop_ro (input+2); r_anal_diff_setup (core->anal, R_FALSE, -1, -1); } else { eprintf ("Usage: cg[o] [file]\n"); eprintf (" cg - byte-per-byte code graph diff\n"); eprintf (" cgo - opcode-bytes code graph diff\n"); return R_FALSE; } if (!(core2 = r_core_new ())) { eprintf ("Cannot init diff core\n"); return R_FALSE; } core2->io->va = core->io->va; core2->anal->split = core->anal->split; if (!r_core_file_open (core2, file2, 0, 0LL)) { eprintf ("Cannot open diff file '%s'\n", file2); r_core_free (core2); return R_FALSE; } // TODO: must replicate on core1 too r_config_set_i (core2->config, "io.va", R_TRUE); r_config_set_i (core2->config, "anal.split", R_TRUE); r_anal_diff_setup (core->anal, diffops, -1, -1); r_anal_diff_setup (core2->anal, diffops, -1, -1); r_core_bin_load (core2, file2); r_core_gdiff (core, core2); r_core_diff_show (core, core2); r_core_free (core2); } break; case '?': r_cons_strcat ( "Usage: c[?cdfx] [argument]\n" " c [string] Compares a plain with escaped chars string\n" //" cc [offset] Code bindiff current block against offset\n" " cd [value] Compare a doubleword from a math expression\n" //" cD [file] Like above, but using radiff -b\n"); " cq [value] Compare a quadword from a math expression\n" " cx [hexpair] Compare hexpair string\n" " cX [addr] Like 'cc' but using hexdiff output\n" " cf [file] Compare contents of file at current seek\n" " cg[o] [file] Graphdiff current file and [file]\n"); break; default: eprintf ("Usage: c[?Ddxf] [argument]\n"); } return 0; }
R_API int r_core_config_init(RCore *core) { int i; char buf[128], *p; RConfig *cfg = cfg = core->config = r_config_new (core); cfg->printf = r_cons_printf; cfg->num = core->num; r_config_set (cfg, "dir.source", ""); r_config_desc (cfg, "dir.source", "Path to find source files"); r_config_set (cfg, "dir.magic", R_MAGIC_PATH); r_config_desc (cfg, "dir.magic", "Path to r_magic files"); r_config_set (cfg, "dir.plugins", LIBDIR"/radare2/"R2_VERSION"/"); r_config_desc (cfg, "dir.plugins", "Path to plugin files to be loaded at startup"); /* anal */ r_config_set (cfg, "anal.prelude", ""); r_config_desc (cfg, "anal.prelude", "Specify an hexpair to find preludes in code"); r_config_set_i (cfg, "anal.depth", 50); // XXX: warn if depth is > 50 .. can be problematic r_config_desc (cfg, "anal.depth", "Max depth at code analysis"); r_config_set_i (cfg, "anal.ptrdepth", 3); r_config_set_cb (cfg, "anal.split", "true", &config_analsplit_callback); r_config_set_cb (cfg, "anal.plugin", R_SYS_ARCH, &config_analplugin_callback); r_config_desc (cfg, "anal.plugin", "Specify the anal plugin to use"); /* asm */ r_config_set_cb (cfg, "asm.arch", R_SYS_ARCH, &config_asmarch_callback); r_config_desc (cfg, "asm.arch", "Set the arch to be usedd by asm"); // XXX: not portable r_parse_use (core->parser, "x86.pseudo"); r_config_set_cb (cfg, "asm.parser", "x86.pseudo", &config_asmparser_callback); r_config_set_i_cb (cfg, "asm.bits", 32, &config_asmbits_callback); r_config_desc (cfg, "asm.bits", "Word size in bits at assembler"); r_config_set (cfg, "asm.bytes", "true"); r_config_desc (cfg, "asm.bytes", "Display the bytes of each instruction"); r_config_set (cfg, "asm.flags", "true"); r_config_desc (cfg, "asm.bytes", "Show flags in disassembly (pd)"); r_config_set (cfg, "asm.size", "false"); r_config_desc (cfg, "asm.size", "Show size of opcodes in disassembly (pd)"); r_config_set (cfg, "asm.lbytes", "true"); r_config_desc (cfg, "asm.lbytes", "Align disasm bytes to left"); r_config_set (cfg, "asm.middle", "false"); // jump in the middle because of antidisasm tricks r_config_set (cfg, "asm.comments", "true"); r_config_desc (cfg, "asm.comments", "Show comments in disassembly view"); r_config_set (cfg, "asm.cmtright", "true"); r_config_desc (cfg, "asm.cmtright", "Show comments at right of disassembly if they fit in screen"); r_config_set (cfg, "asm.ucase", "false"); r_config_desc (cfg, "asm.ucase", "Use uppercase syntax at disassembly"); r_config_set (cfg, "asm.stackptr", "false"); r_config_desc (cfg, "asm.stackptr", "Show stack pointer at disassembly"); r_config_set (cfg, "asm.dwarf", "false"); r_config_desc (cfg, "asm.dwarf", "Show dwarf comment at disassembly"); r_config_set_i (cfg, "asm.nbytes", 8); r_config_set (cfg, "asm.tabs", "false"); r_config_desc (cfg, "asm.nbytes", "Number of bytes for each opcode at disassembly"); r_config_set (cfg, "asm.pseudo", "false"); // DEPRECATED ??? r_config_desc (cfg, "asm.pseudo", "Enable pseudo syntax"); r_config_set (cfg, "asm.filter", "true"); r_config_desc (cfg, "asm.filter", "Show filtered flags at disassembly"); r_config_set (cfg, "asm.varsub", "true"); r_config_desc (cfg, "asm.varsub", "Substitute variables in disasm"); r_config_set (cfg, "asm.trace", "true"); r_config_desc (cfg, "asm.trace", "Show execution traces for each opcode"); r_config_set (cfg, "asm.decode", "false"); r_config_desc (cfg, "asm.decode", "Use code analysis as a disassembler"); r_config_set (cfg, "asm.offset", "true"); r_config_desc (cfg, "asm.offset", "Show offsets at disassembly"); r_config_set (cfg, "asm.offseg", "false"); r_config_desc (cfg, "asm.offseg", "Show offsets as in 16 bit segment addressing mode"); r_config_set (cfg, "asm.lines", "true"); r_config_desc (cfg, "asm.lines", "If enabled show ascci-art lines at disassembly"); r_config_set (cfg, "asm.linesout", "true"); r_config_desc (cfg, "asm.linesout", "If enabled show out of block lines"); r_config_set (cfg, "asm.linesstyle", "false"); r_config_desc (cfg, "asm.linesstyle", "If enabled iterate the jump list backwards"); r_config_set (cfg, "asm.lineswide", "false"); r_config_desc (cfg, "asm.lineswide", "If enabled put an space between lines"); r_config_set_i_cb (cfg, "asm.lineswidth", 10, &config_asmlineswidth_callback); r_config_desc (cfg, "asm.lineswidth", ""); r_config_set (cfg, "asm.linescall", "false"); r_config_desc (cfg, "asm.linescall", "Enable call lines"); r_config_set_cb (cfg, "asm.os", R_SYS_OS, &config_asmos_callback); r_config_desc (cfg, "asm.os", "Select operating system (kernel) (linux, darwin, w32,..)"); r_config_set_cb (cfg, "asm.syntax", "intel", &config_asmsyntax_callback); r_config_desc (cfg, "asm.syntax", "Select assembly syntax"); r_config_set_cb (cfg, "asm.profile", "default", &config_asmprofile_callback); r_config_desc (cfg, "asm.profile", "configure disassembler (default, simple, gas, smart, debug, full)"); /* misc */ #if LIL_ENDIAN r_config_set_cb (cfg, "cfg.bigendian", "false", &config_bigendian_callback); #else r_config_set_cb (cfg, "cfg.bigendian", "true", &config_bigendian_callback); #endif r_config_desc (cfg, "cfg.bigendian", "Use little (false) or big (true) endiannes"); r_config_set_cb (cfg, "cfg.debug", "false", &config_cfgdebug_callback); r_config_desc (cfg, "cfg.debug", "set/unset the debugger mode"); r_config_set_cb (cfg, "cfg.datefmt", "%d:%m:%Y %H:%M:%S %z", &config_cfgdatefmt_callback); r_config_desc (cfg, "cfg.datefmt", "Date format (%d:%m:%Y %H:%M:%S %z)"); r_config_set (cfg, "cfg.fortunes", "true"); r_config_desc (cfg, "cfg.fortunes", "If enabled show tips at start"); r_config_set (cfg, "cfg.wseek", "false"); r_config_desc (cfg, "cfg.wseek", "Seek after write"); r_config_set_i (cfg, "cfg.hashlimit", SLURP_LIMIT); r_config_desc (cfg, "cfg.hashlimit", "If the file its bigger than hashlimit don't calculate the hash"); /* diff */ r_config_set_i (cfg, "diff.from", 0); r_config_desc (cfg, "diff.from", "set source diffing address for px (uses cc command)"); r_config_set_i (cfg, "diff.to", 0); r_config_desc (cfg, "diff.to", "set destination diffing address for px (uses cc command)"); /* debug */ if (core->cons->rows>30) // HACKY r_config_set_i (cfg, "dbg.follow", 64); else r_config_set_i (cfg, "dbg.follow", 32); r_config_desc (cfg, "dbg.follow", "Follow program counter when pc > core->offset + dbg.follow"); r_config_set_cb (cfg, "dbg.backend", "native", &config_dbgbackend_callback); r_config_desc (cfg, "dbg.backend", "Select the debugger backend"); r_config_set (cfg, "dbg.bep", "loader"); // loader, entry, constructor, main r_config_desc (cfg, "cfg.bep", "break on entrypoint (loader, entry, constructor, main)"); r_config_set_cb (cfg, "dbg.stopthreads", "true", &config_stopthreads_callback); r_config_desc (cfg, "dbg.stopthreads", "stop all threads when debugger breaks"); r_config_set_cb (cfg, "dbg.swstep", "false", &config_swstep_callback); r_config_desc (cfg, "dbg.swstep", "If enabled forces the use of software steps (code analysis+breakpoint)"); r_config_set_cb (cfg, "dbg.trace", "true", &config_trace_callback); r_config_desc (cfg, "dbg.trace", "enable debugger trace (see asm.trace)"); r_config_set_cb (cfg, "dbg.trace.tag", "0xff", &config_tracetag_callback); r_config_set_cb (cfg, "fs.view", "normal", &config_fsview_callback); r_config_desc (cfg, "fs.view", "Set visibility options for filesystems"); r_config_set (cfg, "hud.once", "false"); r_config_desc (cfg, "hud.once", "run"); r_config_set (cfg, "bin.strings", "true"); p = r_sys_getenv ("EDITOR"); #if __WINDOWS__ r_config_set (cfg, "cfg.editor", p? p: "notepad"); #else r_config_set (cfg, "cfg.editor", p? p: "vi"); #endif r_config_desc (cfg, "cfg.editor", "Select default editor program"); free (p); if (r_file_exist ("/usr/bin/xdot")) r_config_set (cfg, "cmd.graph", "!xdot a.dot"); else if (r_file_exist ("/usr/bin/open")) r_config_set (cfg, "cmd.graph", "!dot -Tgif -oa.gif a.dot;!open a.gif"); else if (r_file_exist ("/usr/bin/gqview")) r_config_set (cfg, "cmd.graph", "!dot -Tgif -oa.gif a.dot;!gqview a.gif"); else r_config_set (cfg, "cmd.graph", "!dot -Tgif -oa.gif a.dot;!gqview a.gif"); r_config_desc (cfg, "cmd.graph", "Command executed by 'agv' command to view graphs"); r_config_set (cfg, "cmd.hit", ""); r_config_desc (cfg, "cmd.hit", "Command to execute on every search hit"); r_config_set (cfg, "cmd.open", ""); r_config_desc (cfg, "cmd.open", "Command executed when file its opened"); r_config_set_cb (cfg, "cmd.repeat", "true", &config_cmdrepeat_callback); r_config_desc (cfg, "cmd.repeat", "Alias newline (empty command) as '..'"); r_config_set (cfg, "cmd.prompt", ""); r_config_desc (cfg, "cmd.prompt", "Prompt commands"); r_config_set (cfg, "cmd.cprompt", ""); r_config_desc (cfg, "cmd.cprompt", "Column visual prompt commands"); r_config_set (cfg, "cmd.vprompt", ""); r_config_desc (cfg, "cmd.vprompt", "Visual prompt commands"); r_config_set (cfg, "cmd.bp", ""); r_config_desc (cfg, "cmd.bp", "Command to executed every breakpoint hitted"); r_config_set (cfg, "graph.font", "Courier"); r_config_desc (cfg, "graph.font", "font to be used by the dot graphs"); r_config_set_cb (cfg, "scr.sparse", "false", config_scrsparse_callback); r_config_set_cb (cfg, "scr.interactive", "true", config_scrint_callback); r_config_set_cb (cfg, "scr.tee", "", config_teefile_callback); r_config_desc (cfg, "scr.tee", "Pipe console output to file if not empty"); r_config_set_cb (cfg, "scr.prompt", "true", &config_scrprompt_callback); r_config_set_cb (cfg, "scr.color", (core->print->flags&R_PRINT_FLAGS_COLOR)?"true":"false", &config_color_callback); r_config_desc (cfg, "scr.color", "Enable/Disable colors"); r_config_set_cb (cfg, "scr.pager", "", &config_pager_callback); r_config_desc (cfg, "scr.pager", "Select pager program (used if output doesn't fit on window)"); //r_config_set_cb (cfg, "scr.fkey", "function", &config_scrfkey_callback); r_config_set_cb (cfg, "scr.fkey", "hit", &config_scrfkey_callback); r_config_desc (cfg, "scr.fkey", "Select the seek mode in visual"); r_config_set (cfg, "scr.seek", ""); r_config_set_i_cb (cfg, "scr.cols", 16, &config_scrcols_callback); r_config_desc (cfg, "scr.cols", "Configure the number of columns to print"); r_config_set (cfg, "search.in", "file"); r_config_desc (cfg, "search.in", "Specify search boundaries (raw, block, file, section)"); r_config_set_i (cfg, "search.kwidx", 0); r_config_desc (cfg, "search.kwidx", "Store last search index count"); r_config_set (cfg, "search.show", "true"); r_config_desc (cfg, "search.show", "Show search results while found (disable if lot of hits)"); r_config_set (cfg, "search.flags", "true"); r_config_desc (cfg, "search.flags", "If enabled all search results are flagged, else just printed r2 commands"); r_config_set_i (cfg, "search.count", 0); r_config_desc (cfg, "search.count", "Start index number at search hits"); r_config_set (cfg, "search.prefix", "hit"); r_config_desc (cfg, "search.prefix", "Prefix name in search hits label"); r_config_set_i (cfg, "search.from", UT64_MAX); r_config_desc (cfg, "search.from", "Search start address"); r_config_set_i (cfg, "search.to", UT64_MAX); r_config_desc (cfg, "search.to", "Search end address"); r_config_set_i (cfg, "search.distance", 0); // TODO: use i_cb here and remove code in cmd.c r_config_desc (cfg, "search.distance", "Search string distance"); r_config_set_i_cb (cfg, "search.align", 0, &config_searchalign_callback); r_config_desc (cfg, "search.align", "Only catch aligned search hits"); r_config_set_cb (cfg, "scr.html", "false", &config_scrhtml_callback); r_config_desc (cfg, "scr.html", "If enabled disassembly use HTML syntax"); sprintf (buf, "%d", R_CORE_BLOCKSIZE_MAX); r_config_set_cb (cfg, "io.maxblk", buf, &config_iomaxblk_callback); r_config_desc (cfg, "io.maxblk", "set max block size (soft limit)"); r_config_set_cb (cfg, "io.ffio", "true", &config_ioffio_callback); r_config_desc (cfg, "io.ffio", "fill invalid buffers with 0xff instead of returning error"); r_config_set_cb (cfg, "io.va", "true", &config_iova_callback); r_config_desc (cfg, "io.va", "If enabled virtual address layout can be used"); r_config_set_cb (cfg, "io.cache", "false", &config_iocache_callback); r_config_desc (cfg, "io.cache", "Enable cache for io changes"); r_config_set (cfg, "file.analyze", "false"); r_config_desc (cfg, "file.analyze", "Analyze file on load. Same as r2 -c aa .."); r_config_set (cfg, "file.path", ""); r_config_desc (cfg, "file.path", "Path of current file"); r_config_set (cfg, "file.desc", ""); r_config_desc (cfg, "file.desc", "User defined file description. Used by projects"); r_config_set (cfg, "file.project", ""); r_config_desc (cfg, "file.project", "Name of current project"); r_config_set (cfg, "file.md5", ""); r_config_desc (cfg, "file.md5", "md5 sum of current file"); r_config_set (cfg, "file.sha1", ""); r_config_desc (cfg, "file.sha1", "sha1 hash of current file"); r_config_set (cfg, "file.type", ""); r_config_desc (cfg, "file.type", "Type of current file"); r_config_set_i (cfg, "magic.depth", 100); r_config_desc (cfg, "magic.depth", "Recursivity depth in magic description strings"); r_config_set (cfg, "rap.loop", "true"); r_config_desc (cfg, "rap.loop", "run rap as a forever-listening daemon"); /* fkeys */ for (i=1; i<13; i++) { snprintf (buf, sizeof (buf), "key.f%d", i); snprintf (buf+10, sizeof (buf)-10, "Run this when F%d key is pressed in visual mode", i); switch (i) { case 2: p = "dbs $$"; break; case 7: p = "ds"; break; case 8: p = "dso"; break; case 9: p = "dc"; break; default: p = ""; break; } r_config_set (cfg, buf, p); r_config_desc (cfg, buf, buf+10); } /* zoom */ r_config_set_i (cfg, "zoom.maxsz", 512); r_config_desc (cfg, "zoom.maxsz", "Zoom max size of block"); r_config_set_i (cfg, "zoom.from", 0); r_config_desc (cfg, "zoom.from", "Zoom start address"); r_config_set_i (cfg, "zoom.to", 0); r_config_desc (cfg, "zoom.to", "Zoom end address"); r_config_set_cb (cfg, "zoom.byte", "h", &config_zoombyte_callback); r_config_desc (cfg, "zoom.byte", "Zoom specific callback to calculate each byte (See pZ? for help)"); /* TODO cmd */ #if 0 config_set("asm.section", "true"); config_set("asm.reladdr", "false"); // relative offset config_set("asm.functions", "true"); config_set_i("asm.nlines", 6); // show left ref lines config_set("asm.lineswide", "false"); // show left ref lines config_set("asm.trace", "false"); // trace counter config_set("asm.split", "true"); // split code blocks config_set("asm.splitall", "false"); // split code blocks // config_set("asm.follow", ""); config_set("cmd.wp", ""); config_set("cmd.flag", "true"); config_set("cmd.asm", ""); config_set("cmd.user", ""); config_set("cmd.trace", ""); config_set("cmd.visual", ""); config_set("cmd.visualbind", ""); config_set("cmd.touchtrace", ""); config_set("search.flag", "true"); config_set("search.verbose", "true"); config_set("file.id", "false"); config_set("file.flag", "false"); config_set("file.trace", "trace.log"); config_set("file.project", ""); config_set("file.entrypoint", ""); node = config_set("file.scrfilter", ""); node->callback = &config_filterfile_callback; config_set_i("file.size", 0); node = config_set_i("io.vaddr", 0); // OLD file.baddr node->callback = &config_vaddr_callback; node = config_set_i("io.paddr", 0); // physical address node->callback = &config_paddr_callback; config_set("dump.regs", "true"); config_set("dump.user", "true"); config_set("dump.libs", "true"); config_set("dump.fds", "true"); config_set("trace.bt", "false"); config_set("trace.bps", "false"); config_set("trace.calls", "false"); config_set_i("trace.sleep", 0); config_set("trace.smart", "false"); config_set("trace.libs", "true"); config_set("trace.log", "false"); config_set("trace.dup", "false"); config_set("trace.cmtregs", "false"); config_set("cfg.editor", "vi"); node = config_set("cfg.debug", "false"); node->callback = &config_debug_callback; config_set("cfg.noscript", "false"); config_set("cfg.sections", "true"); config_set("cfg.encoding", "ascii"); // cp850 config_set_i("cfg.delta", 4096); // cp850 node = config_set("cfg.verbose", "true"); node->callback = &config_verbose_callback; config_set("cfg.inverse", "false"); config_set_i("cfg.analdepth", 6); config_set("file.insert", "false"); config_set("file.insertblock", "false"); config_set("file.undowrite", "true"); if (first) { node = config_set("file.write", "false"); node->callback = &config_wmode_callback; } node = config_set("cfg.limit", "0"); node->callback = &config_limit_callback; #if __mips__ // ??? config_set("cfg.addrmod", "32"); #else config_set("cfg.addrmod", "4"); #endif config_set("cfg.datefmt", "%d:%m:%Y %H:%M:%S %z"); config_set_i("cfg.count", 0); node = config_set_i("cfg.bsize", 512); node->callback = &config_bsize_callback; config_set_i("cfg.vbsize", 1024); config_set("cfg.vbsize_enabled", "false"); config_set_i("range.from", 0); config_set_i("range.to", 0xffff); config_set("range.traces", "true"); config_set("range.graphs", "true"); config_set("range.functions", "true"); config_set("child.stdio", ""); config_set("child.stdin", ""); config_set("child.stdout", ""); config_set("child.stderr", ""); config_set("child.setgid", ""); // must be int ? config_set("child.chdir", "."); config_set("child.chroot", "/"); config_set("child.setuid", ""); #if __mips__ config_set("dbg.fpregs", "true"); #else config_set("dbg.fpregs", "false"); #endif config_set("dbg.forks", "false"); // stop debugger in any fork or clone config_set("dbg.controlc", "true"); // stop debugger if ^C is pressed config_set_i("dbg.focus", 0); // focus on ps.pid or not (ignore events of rest of procs) config_set("dbg.syms", "true"); config_set("dbg.stepo", "false"); // step over for !contu (debug_step()) config_set("dbg.maps", "true"); config_set("dbg.sections", "true"); config_set("dbg.strings", "false"); config_set("dbg.stop", "false"); config_set("dbg.threads", "false"); config_set("dbg.contscbt", "true"); config_set("dbg.contsc2", "true"); // WTF? config_set("dbg.regs", "true"); config_set("dbg.regs2", "false"); config_set("dbg.stack", "true"); config_set("dbg.vstack", "true"); config_set("dbg.wptrace", "false"); config_set_i("dbg.stacksize", 66); config_set("dbg.stackreg", "esp"); config_set("dbg.bt", "false"); config_set_i("dbg.btlast", 0); config_set("dbg.fullbt", "false"); // user backtrace or lib+user backtrace config_set("dbg.bttype", "default"); // default, st and orig or so! #if __APPLE__ || __ARM__ || __mips__ config_set("dbg.hwbp", "false"); // default, st and orig or so! #else config_set("dbg.hwbp", "true"); // hardware breakpoints by default // ALSO BSD #endif config_set("dir.home", getenv("HOME")); /* dir.monitor */ ptr = getenv("MONITORPATH"); if (ptr == NULL) { sprintf(buf, "%s/.radare/monitor/", ("HOME")); ptr = (const char *)&buf; } config_set("dir.monitor", ptr); config_set("graph.split", "false"); // split blocks // SHOULD BE TRUE, but true algo is buggy config_set("graph.jmpblocks", "true"); config_set("graph.refblocks", "false"); // must be circle nodes config_set("graph.callblocks", "false"); config_set("graph.flagblocks", "true"); config_set_i("graph.depth", 9); config_set("graph.offset", "true"); config_set("graph.render", "cairo"); // aalib/ncurses/text config_set("graph.layout", "default"); // graphviz #endif r_config_lock (cfg, R_TRUE); return R_TRUE; }
int main(int argc, char **argv) { const char *addr = NULL; RCore *c, *c2; RDiff *d; const char *arch = NULL; int bits = 0; char *file, *file2; ut8 *bufa, *bufb; int o, sza, szb, rad = 0, delta = 0; int mode = MODE_DIFF; int diffops = 0; int threshold = -1; double sim; while ((o = getopt (argc, argv, "a:b:Cnpg:Orhcdsvxt:")) != -1) { switch (o) { case 'a': arch = optarg; break; case 'b': bits = atoi (optarg); break; case 'p': useva = R_FALSE; break; case 'r': rad = 1; break; case 'g': mode = MODE_GRAPH; addr = optarg; break; case 'c': showcount = 1; break; case 'C': mode = MODE_CODE; break; case 'n': showbare = R_TRUE; break; case 'O': diffops = 1; break; case 't': threshold = atoi (optarg); break; case 'd': delta = 1; break; case 'h': return show_help (1); case 's': mode = MODE_DIST; break; case 'x': mode = MODE_COLS; break; case 'v': printf ("radiff2 v"R2_VERSION"\n"); return 0; default: return show_help (0); } } if (argc<3 || optind+2>argc) return show_help (0); file = argv[optind]; file2 = argv[optind+1]; switch (mode) { case MODE_GRAPH: case MODE_CODE: c = opencore (file); if (!c) eprintf ("Cannot open '%s'\n", file); c2 = opencore (file2); if (!c || !c2) { eprintf ("Cannot open '%s'\n", file2); return 1; } if (arch) { r_config_set (c->config, "asm.arch", arch); r_config_set (c2->config, "asm.arch", arch); } if (bits) { r_config_set_i (c->config, "asm.bits", bits); r_config_set_i (c2->config, "asm.bits", bits); } r_config_set_i (c->config, "diff.bare", showbare); r_config_set_i (c2->config, "diff.bare", showbare); r_anal_diff_setup_i (c->anal, diffops, threshold, threshold); r_anal_diff_setup_i (c2->anal, diffops, threshold, threshold); if (mode == MODE_GRAPH) { const char* second = strstr (addr, ","); if (!second) { r_core_gdiff (c, c2, R_TRUE); r_core_anal_graph (c, r_num_math (c->num, addr), R_CORE_ANAL_GRAPHBODY|R_CORE_ANAL_GRAPHDIFF); } else { const ut64 off = strtoull(addr, 0, 16); // define the same function at each offset r_core_anal_fcn (c, off, UT64_MAX, R_ANAL_REF_TYPE_NULL, 0); r_core_anal_fcn (c2, strtoull (second+1, 0, 16), UT64_MAX, R_ANAL_REF_TYPE_NULL, 0); r_core_gdiff (c, c2, R_FALSE); // compute the diff r_core_anal_graph (c, off, R_CORE_ANAL_GRAPHBODY|R_CORE_ANAL_GRAPHDIFF); } } else { r_core_gdiff (c, c2, R_TRUE); r_core_diff_show (c, c2); } return 0; } bufa = (ut8*)r_file_slurp (file, &sza); if (!bufa) { eprintf ("radiff2: Can not open %s\n", bufa); return 1; } bufb = (ut8*)r_file_slurp (file2, &szb); if (!bufb) { eprintf ("radiff2: Cannot open: %s\n", bufb); free (bufa); return 1; } switch (mode) { case MODE_COLS: { int cols = (r_cons_get_size (NULL)>112)?16:8; dump_cols (bufa, sza, bufb, szb, cols); } break; case MODE_DIFF: d = r_diff_new (0LL, 0LL); r_diff_set_delta (d, delta); r_diff_set_callback (d, &cb, (void *)(size_t)rad); r_diff_buffers (d, bufa, sza, bufb, szb); r_diff_free (d); break; case MODE_DIST: r_diff_buffers_distance (NULL, bufa, sza, bufb, szb, &count, &sim); printf ("similarity: %.2f\n", sim); printf ("distance: %d\n", count); break; } if (showcount) printf ("%d\n", count); free (bufa); free (bufb); return 0; }