R_API int r_core_lines_initcache(RCore *core, ut64 start_addr, ut64 end_addr) { int i, line_count; int bsz = core->blocksize; char *buf; ut64 off = start_addr; ut64 baddr; if (start_addr == UT64_MAX || end_addr == UT64_MAX) { return -1; } free (core->print->lines_cache); core->print->lines_cache = R_NEWS0 (ut64, bsz); if (!core->print->lines_cache) { return -1; } { RIOSection *s = r_io_section_mget_in (core->io, core->offset); baddr = s? s->paddr: r_config_get_i (core->config, "bin.baddr"); } line_count = start_addr? 0: 1; core->print->lines_cache[0] = start_addr? 0: baddr; buf = malloc (bsz); if (!buf) { return -1; } r_cons_break_push (NULL, NULL); while (off < end_addr) { if (r_cons_is_breaked ()) { break; } r_io_read_at (core->io, off, (ut8 *) buf, bsz); for (i = 0; i < bsz; i++) { if (buf[i] == '\n') { core->print->lines_cache[line_count] = start_addr? off + i + 1: off + i + 1 + baddr; line_count++; if (line_count % bsz == 0) { ut64 *tmp = realloc (core->print->lines_cache, (line_count + bsz) * sizeof (ut64)); if (tmp) { core->print->lines_cache = tmp; } else { R_FREE (core->print->lines_cache); goto beach; } } } } off += bsz; } free (buf); r_cons_break_pop (); return line_count; beach: free (buf); r_cons_break_pop (); return -1; }
static int r_debug_bochs_wait(RDebug *dbg, int pid) { char strIP[19]; int i = 0; const char *x; char *ini = 0, *fin = 0; //eprintf ("bochs_wait:\n"); if (bStep) { bStep = false; } else { r_cons_break_push (bochs_debug_break, dbg); i = 500; do { bochs_wait (desc); if (bBreak) { if (desc->data[0]) { eprintf ("ctrl+c %s\n", desc->data); bBreak = false; break; } i--; if (!i) { bBreak = false; eprintf ("empty ctrl+c.\n"); break; } } else if (desc->data[0]) { //eprintf("stop on breakpoint%s\n",desc->data); break; } } while(1); r_cons_break_pop (); } //eprintf ("bochs_wait: loop done\n"); i = 0; // Next at t=394241428 // (0) [0x000000337635] 0020:0000000000337635 (unk. ctxt): add eax, esi ; 03c6 ripStop = 0; if ((x = strstr (desc->data, "Next at"))) { if ((ini = strstr (x, "[0x"))) { if ((fin = strstr (ini,"]"))) { int len = fin - ini - 1; strncpy (strIP, ini+1, len); strIP[len] = 0; //eprintf(" parada EIP = %s\n",strIP); ripStop = r_num_get (NULL, strIP); } } } desc->data[0] = 0; return true; }
R_API bool r_core_dump(RCore *core, const char *file, ut64 addr, ut64 size, int append) { ut64 i; ut8 *buf; int bs = core->blocksize; FILE *fd; if (append) { fd = r_sandbox_fopen (file, "ab"); } else { r_sys_truncate (file, 0); fd = r_sandbox_fopen (file, "wb"); } if (!fd) { eprintf ("Cannot open '%s' for writing\n", file); return false; } /* some io backends seems to be buggy in those cases */ if (bs > 4096) { bs = 4096; } buf = malloc (bs); if (!buf) { eprintf ("Cannot alloc %d byte(s)\n", bs); fclose (fd); return false; } r_cons_break_push (NULL, NULL); for (i = 0; i < size; i += bs) { if (r_cons_is_breaked ()) { break; } if ((i + bs) > size) { bs = size - i; } r_io_read_at (core->io, addr + i, buf, bs); if (fwrite (buf, bs, 1, fd) < 1) { eprintf ("write error\n"); break; } } r_cons_break_pop (); fclose (fd); free (buf); return true; }
static void rtti_msvc_print_all(RVTableContext *context, int mode) { r_cons_break_push (NULL, NULL); RList *vtables = r_anal_vtable_search (context); RListIter *vtableIter; RVTableInfo *table; if (vtables) { r_list_foreach (vtables, vtableIter, table) { if (r_cons_is_breaked ()) { break; } r_anal_rtti_msvc_print_at_vtable (context, table->saddr, mode); r_cons_print ("\n"); } } r_list_free (vtables); r_cons_break_pop (); }
static void draw_vertical_line (RConsCanvas *c, int x, int y, int height) { int i; /* do not render offscreen vertical lines */ if (x + c->sx < 0) { return; } if (x + c->sx > c->w) { return; } const char *vline = useUtf8? RUNECODESTR_LINE_VERT : "|"; r_cons_break_push (NULL, NULL); for (i = y; i < y + height; i++) { if (r_cons_is_breaked ()) { break; } if (G (x, i)) { W (vline); } } r_cons_break_pop (); }
R_API ut64 r_debug_esil_step(RDebug *dbg, ut32 count) { count++; has_match = 0; r_cons_break_push (NULL, NULL); do { if (r_cons_is_breaked ()) { break; } if (has_match) { eprintf ("EsilBreak match at 0x%08"PFMT64x"\n", opc); break; } if (count > 0) { count--; if (!count) { //eprintf ("Limit reached\n"); break; } } } while (r_debug_esil_stepi (dbg)); r_cons_break_pop (); return opc; }
// TODO: add support for byte-per-byte opcode search R_API RList *r_core_asm_strsearch(RCore *core, const char *input, ut64 from, ut64 to, int maxhits, int regexp) { RCoreAsmHit *hit; RAsmOp op; RList *hits; ut64 at, toff = core->offset; ut8 *buf; int align = core->search->align; RRegex* rx = NULL; char *tok, *tokens[1024], *code = NULL, *ptr; int idx, tidx = 0, len; int tokcount, matchcount, count = 0; int matches = 0, addrbytes = core->assembler->addrbytes; if (!*input) { return NULL; } if (core->blocksize <= OPSZ) { eprintf ("error: block size too small\n"); return NULL; } if (!(buf = (ut8 *)calloc (core->blocksize, 1))) { return NULL; } if (!(ptr = strdup (input))) { free (buf); return NULL; } if (!(hits = r_core_asm_hit_list_new ())) { free (buf); free (ptr); return NULL; } tokens[0] = NULL; for (tokcount = 0; tokcount < R_ARRAY_SIZE (tokens) - 1; tokcount++) { tok = strtok (tokcount? NULL: ptr, ";"); if (!tok) break; tokens[tokcount] = r_str_trim_head_tail (tok); } tokens[tokcount] = NULL; r_cons_break_push (NULL, NULL); for (at = from, matchcount = 0; at < to; at += core->blocksize) { matches = 0; if (r_cons_is_breaked ()) { break; } if (!r_io_read_at (core->io, at, buf, core->blocksize)) { break; } idx = 0, matchcount = 0; while (addrbytes * (idx + 1) <= core->blocksize) { ut64 addr = at + idx; r_asm_set_pc (core->assembler, addr); if (!(len = r_asm_disassemble ( core->assembler, &op, buf + addrbytes * idx, core->blocksize - addrbytes * idx))) { idx = (matchcount)? tidx + 1: idx + 1; matchcount = 0; continue; } matches = strcmp (op.buf_asm, "invalid") && strcmp (op.buf_asm, "unaligned"); if (matches && tokens[matchcount]) { if (!regexp) { matches = strstr(op.buf_asm, tokens[matchcount]) != NULL; } else { rx = r_regex_new (tokens[matchcount], ""); matches = r_regex_exec (rx, op.buf_asm, 0, 0, 0) == 0; r_regex_free (rx); } } if (align && align > 1) { if (addr % align) { matches = false; } } if (matches) { code = r_str_appendf (code, "%s; ", op.buf_asm); if (matchcount == tokcount - 1) { if (tokcount == 1) { tidx = idx; } if (!(hit = r_core_asm_hit_new ())) { r_list_purge (hits); free (hits); hits = NULL; goto beach; } hit->addr = addr; hit->len = idx + len - tidx; if (hit->len == -1) { r_core_asm_hit_free (hit); goto beach; } code[strlen (code)-2] = 0; hit->code = strdup (code); r_list_append (hits, hit); R_FREE (code); matchcount = 0; idx = tidx + 1; if (maxhits) { count++; if (count >= maxhits) { //eprintf ("Error: search.maxhits reached\n"); goto beach; } } } else if (!matchcount) { tidx = idx; matchcount++; idx += len; } else { matchcount++; idx += len; } } else { idx = matchcount? tidx + 1: idx + 1; R_FREE (code); matchcount = 0; } } } r_cons_break_pop (); r_asm_set_pc (core->assembler, toff); beach: free (buf); free (ptr); free (code); r_cons_break_pop (); return hits; }
static void draw_horizontal_line (RConsCanvas *c, int x, int y, int width, int style) { const char *l_corner = "?", *r_corner = "?"; int i; if (width < 1) { return; } /* do not render offscreen horizontal lines */ if (y + c->sy < 0) { return; } if (y + c->sy > c->h) { return; } switch (style) { case APEX_DOT: if (useUtf8) { if (useUtf8Curvy) { l_corner = RUNECODESTR_CURVE_CORNER_BL; r_corner = RUNECODESTR_CURVE_CORNER_TR; } else { l_corner = RUNECODESTR_CORNER_BL; r_corner = RUNECODESTR_CORNER_TR; } } else { l_corner = "'"; r_corner = "."; } break; case DOT_APEX: if (useUtf8) { if (useUtf8Curvy) { l_corner = RUNECODESTR_CURVE_CORNER_TL; r_corner = RUNECODESTR_CURVE_CORNER_BR; } else { l_corner = RUNECODESTR_CORNER_TL; r_corner = RUNECODESTR_CORNER_BR; } } else { l_corner = "."; r_corner = "'"; } break; case REV_APEX_APEX: if (useUtf8) { if (useUtf8Curvy) { l_corner = RUNECODESTR_CURVE_CORNER_BL; r_corner = RUNECODESTR_CURVE_CORNER_BR; } else { l_corner = RUNECODESTR_CORNER_BL; r_corner = RUNECODESTR_CORNER_BR; } } else { l_corner = "`"; r_corner = "'"; } break; case DOT_DOT: if (useUtf8) { if (useUtf8Curvy) { l_corner = RUNECODESTR_CURVE_CORNER_TL; r_corner = RUNECODESTR_CURVE_CORNER_TR; } else { l_corner = RUNECODESTR_CORNER_TL; r_corner = RUNECODESTR_CORNER_TR; } } else { l_corner = r_corner = "."; } break; case NRM_DOT: if (useUtf8) { l_corner = RUNECODESTR_LINE_HORIZ; if (useUtf8Curvy) { r_corner = RUNECODESTR_CURVE_CORNER_TR; } else { r_corner = RUNECODESTR_CORNER_TR; } } else { l_corner = "-"; r_corner = "."; } break; case NRM_APEX: if (useUtf8) { l_corner = RUNECODESTR_LINE_HORIZ; if (useUtf8Curvy) { r_corner = RUNECODESTR_CURVE_CORNER_BR; } else { r_corner = RUNECODESTR_CORNER_BR; } } else { l_corner = "-"; r_corner = "'"; } break; case DOT_NRM: if (useUtf8) { if (useUtf8Curvy) { l_corner = RUNECODESTR_CURVE_CORNER_TL; } else { l_corner = RUNECODESTR_CORNER_TL; } r_corner = RUNECODESTR_LINE_HORIZ; } else { l_corner = "."; r_corner = "-"; } break; case REV_APEX_NRM: if (useUtf8) { if (useUtf8Curvy) { l_corner = RUNECODESTR_CURVE_CORNER_BL; } else { l_corner = RUNECODESTR_CORNER_BL; } r_corner = RUNECODESTR_LINE_HORIZ; } else { l_corner = "`"; r_corner = "-"; } break; case NRM_NRM: default: if (useUtf8) { l_corner = r_corner = RUNECODESTR_LINE_HORIZ; } else { l_corner = r_corner = "-"; } break; } if (G (x, y)) { W (l_corner); } const char *hline = useUtf8? RUNECODESTR_LINE_HORIZ : "-"; r_cons_break_push (NULL, NULL); for (i = x + 1; i < x + width - 1; i++) { if (r_cons_is_breaked ()) { break; } if (G (i, y)) { W (hline); } } r_cons_break_pop (); if (G (x + width - 1, y)) { W (r_corner); } }
R_API void r_cons_flush() { const char *tee = I.teefile; if (I.noflush) { return; } if (I.null) { r_cons_reset (); return; } r_cons_filter (); if (I.is_interactive && I.fdout == 1) { /* Use a pager if the output doesn't fit on the terminal window. */ if (I.pager && *I.pager && I.buffer_len > 0 && r_str_char_count (I.buffer, '\n') >= I.rows) { I.buffer[I.buffer_len-1] = 0; r_sys_cmd_str_full (I.pager, I.buffer, NULL, NULL, NULL); r_cons_reset (); } else if (I.buffer_len > CONS_MAX_USER) { #if COUNT_LINES int i, lines = 0; for (i = 0; I.buffer[i]; i++) { if (I.buffer[i] == '\n') { lines ++; } } if (lines > 0 && !r_cons_yesno ('n',"Do you want to print %d lines? (y/N)", lines)) { r_cons_reset (); return; } #else char buf[64]; char *buflen = r_num_units (buf, I.buffer_len); if (buflen && !r_cons_yesno ('n',"Do you want to print %s chars? (y/N)", buflen)) { r_cons_reset (); return; } #endif // fix | more | less problem r_cons_set_raw (1); } } if (tee && *tee) { FILE *d = r_sandbox_fopen (tee, "a+"); if (d) { if (I.buffer_len != fwrite (I.buffer, 1, I.buffer_len, d)) { eprintf ("r_cons_flush: fwrite: error (%s)\n", tee); } fclose (d); } else { eprintf ("Cannot write on '%s'\n", tee); } } r_cons_highlight (I.highlight); // is_html must be a filter, not a write endpoint if (I.is_html) { r_cons_html_print (I.buffer); } else { if (I.is_interactive && !r_sandbox_enable (false)) { if (I.linesleep > 0 && I.linesleep < 1000) { int i = 0; int pagesize = R_MAX (1, I.pagesize); char *ptr = I.buffer; char *nl = strchr (ptr, '\n'); int len = I.buffer_len; I.buffer[I.buffer_len] = 0; r_cons_break_push (NULL, NULL); while (nl && !r_cons_is_breaked ()) { r_cons_write (ptr, nl - ptr + 1); if (!(i % pagesize)) { r_sys_usleep (I.linesleep * 1000); } ptr = nl + 1; nl = strchr (ptr, '\n'); i++; } r_cons_write (ptr, I.buffer + len - ptr); r_cons_break_pop (); } else { r_cons_write (I.buffer, I.buffer_len); } } else { r_cons_write (I.buffer, I.buffer_len); } } r_cons_reset (); if (I.newline) { eprintf ("\n"); I.newline = false; } }
/* Callback to trigger SIGINT signal */ static void r_debug_native_stop(RDebug *dbg) { r_debug_kill (dbg, dbg->pid, dbg->tid, SIGINT); r_cons_break_pop (); }
// TODO: add support for byte-per-byte opcode search R_API RList *r_core_asm_strsearch(RCore *core, const char *input, ut64 from, ut64 to, int maxhits, int regexp, int everyByte, int mode) { RCoreAsmHit *hit; RAsmOp op; RList *hits; ut64 at, toff = core->offset; ut8 *buf; int align = core->search->align; RRegex* rx = NULL; char *tok, *tokens[1024], *code = NULL, *ptr; int idx, tidx = 0, len = 0; int tokcount, matchcount, count = 0; int matches = 0; const int addrbytes = core->io->addrbytes; if (!input || !*input) { return NULL; } ut64 usrimm = r_num_math (core->num, input + 1); if (core->blocksize < 8) { eprintf ("error: block size too small\n"); return NULL; } if (!(buf = (ut8 *)calloc (core->blocksize, 1))) { return NULL; } if (!(ptr = strdup (input))) { free (buf); return NULL; } if (!(hits = r_core_asm_hit_list_new ())) { free (buf); free (ptr); return NULL; } tokens[0] = NULL; for (tokcount = 0; tokcount < R_ARRAY_SIZE (tokens) - 1; tokcount++) { tok = strtok (tokcount? NULL: ptr, ";"); if (!tok) { break; } tokens[tokcount] = r_str_trim_head_tail (tok); } tokens[tokcount] = NULL; r_cons_break_push (NULL, NULL); char *opst = NULL; for (at = from, matchcount = 0; at < to; at += core->blocksize) { if (r_cons_is_breaked ()) { break; } if (!r_io_is_valid_offset (core->io, at, 0)) { break; } (void)r_io_read_at (core->io, at, buf, core->blocksize); idx = 0, matchcount = 0; while (addrbytes * (idx + 1) <= core->blocksize) { ut64 addr = at + idx; if (addr >= to) { break; } r_asm_set_pc (core->assembler, addr); if (mode == 'i') { RAnalOp analop = {0}; if (r_anal_op (core->anal, &analop, addr, buf + idx, 15, 0) < 1) { idx ++; // TODO: honor mininstrsz continue; } if (analop.val == usrimm) { if (!(hit = r_core_asm_hit_new ())) { r_list_purge (hits); R_FREE (hits); goto beach; } hit->addr = addr; hit->len = analop.size; // idx + len - tidx; if (hit->len == -1) { r_core_asm_hit_free (hit); goto beach; } r_asm_disassemble (core->assembler, &op, buf + addrbytes * idx, core->blocksize - addrbytes * idx); hit->code = r_str_newf (r_strbuf_get (&op.buf_asm)); idx = (matchcount)? tidx + 1: idx + 1; matchcount = 0; r_list_append (hits, hit); continue; } r_anal_op_fini (&analop); idx ++; // TODO: honor mininstrsz continue; } else if (mode == 'e') { RAnalOp analop = {0}; if (r_anal_op (core->anal, &analop, addr, buf + idx, 15, R_ANAL_OP_MASK_ESIL) < 1) { idx ++; // TODO: honor mininstrsz continue; } //opsz = analop.size; opst = strdup (r_strbuf_get (&analop.esil)); r_anal_op_fini (&analop); } else { if (!(len = r_asm_disassemble ( core->assembler, &op, buf + addrbytes * idx, core->blocksize - addrbytes * idx))) { idx = (matchcount)? tidx + 1: idx + 1; matchcount = 0; continue; } //opsz = op.size; opst = strdup (r_strbuf_get (&op.buf_asm)); } if (opst) { matches = strcmp (opst, "invalid") && strcmp (opst, "unaligned"); } if (matches && tokens[matchcount]) { if (!regexp) { matches = strstr (opst, tokens[matchcount]) != NULL; } else { rx = r_regex_new (tokens[matchcount], ""); if (r_regex_comp (rx, tokens[matchcount], R_REGEX_EXTENDED|R_REGEX_NOSUB) == 0) { matches = r_regex_exec (rx, opst, 0, 0, 0) == 0; } r_regex_free (rx); } } if (align && align > 1) { if (addr % align) { matches = false; } } if (matches) { code = r_str_appendf (code, "%s; ", opst); if (matchcount == tokcount - 1) { if (tokcount == 1) { tidx = idx; } if (!(hit = r_core_asm_hit_new ())) { r_list_purge (hits); R_FREE (hits); goto beach; } hit->addr = addr; hit->len = idx + len - tidx; if (hit->len == -1) { r_core_asm_hit_free (hit); goto beach; } code[strlen (code) - 2] = 0; hit->code = strdup (code); r_list_append (hits, hit); R_FREE (code); matchcount = 0; idx = tidx + 1; if (maxhits) { count++; if (count >= maxhits) { //eprintf ("Error: search.maxhits reached\n"); goto beach; } } } else if (!matchcount) { tidx = idx; matchcount++; idx += len; } else { matchcount++; idx += len; } } else { if (everyByte) { idx = matchcount? tidx + 1: idx + 1; } else { idx += R_MAX (1, len); } R_FREE (code); matchcount = 0; } R_FREE (opst); } } r_cons_break_pop (); r_asm_set_pc (core->assembler, toff); beach: free (buf); free (ptr); free (code); R_FREE (opst); r_cons_break_pop (); return hits; }