int test_num(RNum *num, const char *str, ut64 okvalue) { ut64 ret; printf(" %"PFMT64d" == ", okvalue); ret = r_num_math(num, str); printf("%"PFMT64d" \t; %s", ret, str); if (ret == okvalue) printf("\r ok\n"); else printf("\rFAIL\n"); }
static int cmd_meta(void *data, const char *input) { RCore *core = (RCore*)data; int i; RAnalFunction *f; switch (*input) { case 'j': case '*': r_meta_list (core->anal, R_META_TYPE_ANY, *input); break; case 'L': cmd_meta_lineinfo (core, input + 1); break; case 'C': cmd_meta_comment (core, input); break; case 'h': /* comment */ case 's': /* string */ case 'd': /* data */ case 'm': /* magic */ case 'f': /* formatted */ cmd_meta_hsdmf (core, input); break; case '-': if (input[1]!='*') { i = r_num_math (core->num, input+((input[1]==' ')?2:1)); r_meta_del (core->anal, R_META_TYPE_ANY, core->offset, i, ""); } else r_meta_cleanup (core->anal, 0LL, UT64_MAX); break; case '\0': case '?':{ const char* help_msg[] = { "Usage:", "C[-LCvsdfm?] [...]", " # Metadata management", "C*", "", "list meta info in r2 commands", "C-", " [len] [[@]addr]", "delete metadata at given address range", "CL", "[-][*] [file:line] [addr]", "show or add 'code line' information (bininfo)", "CC", "[-] [comment-text] [@addr]", "add/remove comment", "CC!", " [@addr]", "edit comment with $EDITOR", "CCa", "[-at]|[at] [text] [@addr]", "add/remove comment at given address", "CCu", " [comment-text] [@addr]", "add unique comment", "Cs", "[-] [size] [@addr]", "add string", "Ch", "[-] [size] [@addr]", "hide data", "Cd", "[-] [size] [@addr]", "hexdump data", "Cf", "[-] [sz] [fmt..] [@addr]", "format memory (see pf?)", "Cm", "[-] [sz] [fmt..] [@addr]", "magic parse (see pm?)", NULL}; r_core_cmd_help (core, help_msg); } break; case 'F': f = r_anal_get_fcn_in (core->anal, core->offset, R_ANAL_FCN_TYPE_FCN|R_ANAL_FCN_TYPE_SYM); if (f) r_anal_str_to_fcn (core->anal, f, input+2); else eprintf ("Cannot find function here\n"); break; } return R_TRUE; }
static bool cmd_wf(RCore *core, const char *input) { ut8 *buf; int size; const char *arg = input + ((input[1] == ' ') ? 2 : 1); int wseek = r_config_get_i (core->config, "cfg.wseek"); char *p, *a = r_str_chop (strdup (arg)); // XXX: file names cannot contain spaces p = strchr (a, ' '); if (p) *p++ = 0; if (*arg =='?' || !*arg) { eprintf ("Usage: wf [file] ([size] ([offset]))\n"); } if (!strcmp (arg, "-")) { char *out = r_core_editor (core, NULL, NULL); if (out) { r_io_write_at (core->io, core->offset, (ut8*)out, strlen (out)); free (out); } } if ((buf = (ut8*) r_file_slurp (a, &size))) { int u_size = size; int u_offset = 0; u_size = r_num_math (core->num, p); if (u_size < 1) u_size = size; if (p) { *p++ = 0; u_offset = r_num_math (core->num, p); if (u_offset > size) { eprintf ("Invalid offset\n"); free (buf); return false; } } r_io_use_desc (core->io, core->file->desc); r_io_write_at (core->io, core->offset, buf + u_offset, u_size); WSEEK (core, size); free (buf); r_core_block_read (core, 0); } else { eprintf ("Cannot open file '%s'\n", arg); } return true; }
static int cmd_meta(void *data, const char *input) { RCore *core = (RCore*)data; int i; char *t = 0; RAnalFunction *f; switch (*input) { case 'j': case '*': r_meta_list (core->anal, R_META_TYPE_ANY, *input); break; case 'L': cmd_meta_lineinfo (core, input + 1); break; case 'C': cmd_meta_comment (core, input); break; case 'h': /* comment */ case 's': /* string */ case 'd': /* data */ case 'm': /* magic */ case 'f': /* formatted */ cmd_meta_hsdmf (core, input); break; case '-': if (input[1]!='*') { i = r_num_math (core->num, input+((input[1]==' ')?2:1)); r_meta_del (core->anal, R_META_TYPE_ANY, core->offset, i, ""); } else r_meta_cleanup (core->anal, 0LL, UT64_MAX); break; case '\0': case '?': r_cons_strcat ( "|Usage: C[-LCvsdfm?] [...]\n" "| C* List meta info in r2 commands\n" "| C- [len] [@][ addr] delete metadata at given address range\n" "| CL[-][*] [file:line] [addr] show or add 'code line' information (bininfo)\n" "| CC[-] [comment-text] add/remove comment. Use CC! to edit with $EDITOR\n" "| CCa[-at]|[at] [text] add/remove comment at given address\n" "| Cs[-] [size] [[addr]] add string\n" "| Ch[-] [size] [@addr] hide data\n" "| Cd[-] [size] hexdump data\n" "| Cf[-] [sz] [fmt..] format memory (see pf?)\n" "| Cm[-] [sz] [fmt..] magic parse (see pm?)\n"); break; case 'F': f = r_anal_fcn_find (core->anal, core->offset, R_ANAL_FCN_TYPE_FCN|R_ANAL_FCN_TYPE_SYM); if (f) r_anal_str_to_fcn (core->anal, f, input+2); else eprintf ("Cannot find function here\n"); break; } if (t) free (t); return R_TRUE; }
static int format_output (char mode, const char *s) { ut64 n = r_num_math (num, s); const char *str = (char*) &n; char strbits[65]; if (flags & 2) { /* swap endian */ ut32 n2 = (n>>32)? 8:4; r_mem_copyendian ((ut8*) str, (ut8*) str, n2, 0); }
R_API ut64 r_reg_set_bvalue(RReg *reg, RRegItem *item, const char *str) { ut64 num; if (!item->flags) return UT64_MAX; num = r_str_bits_from_string (str, item->flags); if (num == UT64_MAX) r_reg_set_value (reg, item, r_num_math (NULL, str)); else r_reg_set_value (reg, item, num); return num; }
static int rax(const char *str) { ut64 n; if (*str=='q') return 0; n = r_num_math(NULL, str); if (str[0]=='0'&&str[1]=='x') printf("%"PFMT64d"\n", n); else printf("0x%"PFMT64x"\n", n); return 1; }
R_API ut64 r_reg_set_bvalue(RReg *reg, RRegItem *item, const char *str) { ut64 num = UT64_MAX; if (item && item->flags && str) { num = r_str_bits_from_string (str, item->flags); if (num == UT64_MAX) { num = r_num_math (NULL, str); } r_reg_set_value (reg, item, num); } return num; }
static RIODesc* __open(RIO* io, const char* pathname, int rw, int mode) { RIONull* null; if (__plugin_open (io, pathname,0)) { if (!strncmp (pathname, "null://", 7) && strlen (pathname + 7)) { null = R_NEW0 (RIONull); null->size = r_num_math (NULL, pathname + 7) + 1; //??? null->offset = 0LL; return r_io_desc_new (io, &r_io_plugin_null, pathname, rw, mode, null); } } return NULL; }
R_API int r_core_yank_file_ex (RCore *core, const char *input) { ut64 len = 0, adv = 0, addr = 0; int res = R_FALSE; if (!input) return res; // get the number of bytes to yank adv = consume_chars (input, ' '); len = r_num_math (core->num, input+adv); if (len == 0) { eprintf ("ERROR: Number of bytes read must be > 0\n"); return res; } // get the addr/offset from in the file we want to read adv += find_next_char (input+adv, ' '); if (adv == 0) { eprintf ("ERROR: Address must be specified\n"); return res; } adv++; IFDBG eprintf ("Handling the input: %s\n", input+adv); // XXX - bug, will fail if address needs to be computed and has spaces addr = r_num_math (core->num, input+adv); adv += find_next_char (input+adv, ' '); if (adv == 0) { eprintf ("ERROR: File must be specified\n"); return res; } adv++; IFDBG eprintf ("Filename: %s\n", input+adv); // grab the current file descriptor, so we can reset core and io state // after our io op is done return perform_mapped_file_yank (core, addr, len, input+adv); }
R_API int r_core_yank_to(RCore *core, const char *_arg) { ut64 src = core->offset; ut64 len = 0; ut64 pos = -1; char *str, *arg; ut8 *buf; while (*_arg==' ') _arg++; arg = strdup (_arg); str = strchr (arg, ' '); if (str) { str[0]='\0'; len = r_num_math (core->num, arg); pos = r_num_math (core->num, str+1); str[0]=' '; } if ((str == NULL) || (pos == -1) || (len == 0)) { eprintf ("Usage: yt [len] [dst-addr]\n"); free (arg); return 1; } #if 0 if (!config_get("file.write")) { eprintf("You are not in read-write mode.\n"); return 1; } #endif buf = (ut8*)malloc (len); r_core_read_at (core, src, buf, len); r_core_write_at (core, pos, buf, len); free (buf); core->offset = src; r_core_block_read (core, 0); free (arg); return 0; }
R_API RAnalMetaItem *r_meta_find_in(RAnal *a, ut64 at, int type, int where) { char *res = meta_inrange_get (a, at, 1); if (!res) { return NULL; } RList *list = r_str_split_list (res, ","); RListIter *iter; const char *meta; r_list_foreach (list, iter, meta) { ut64 mia = r_num_math (NULL, meta); RAnalMetaItem *mi = r_meta_find (a, mia, type, where); if (mi && (at >= mi->from && at < mi->to)) { free (res); return mi; } }
R_API char *r_type_get_struct_memb(Sdb *TDB, const char *type, int offset) { int i, typesize = 0; char *res = NULL; if (offset < 0) { return NULL; } char* query = sdb_fmt ("struct.%s", type); char *members = sdb_get (TDB, query, 0); if (!members) { //eprintf ("%s is not a struct\n", type); return NULL; } int nargs = r_str_split (members, ','); for (i = 0; i < nargs ; i++) { const char *name = r_str_word_get0 (members, i); if (!name) { break; } query = sdb_fmt ("struct.%s.%s", type, name); char *subtype = sdb_get (TDB, query, 0); if (!subtype) { break; } int len = r_str_split (subtype, ','); if (len < 3) { free (subtype); break; } int val = r_num_math (NULL, r_str_word_get0 (subtype, len - 1)); int arrsz = val ? val : 1; if ((typesize / 8) == offset) { res = r_str_newf ("%s.%s", type, name); free (subtype); break; } typesize += r_type_get_bitsize (TDB, subtype) * arrsz; free (subtype); } free (members); return res; }
R_API void r_core_rtr_remove(RCore *core, const char *input) { int fd, i; if (input[0] >= '0' && input[0] <= '9') { fd = r_num_math (core->num, input); for (i = 0; i < RTR_MAX_HOSTS; i++) if (rtr_host[i].fd->fd == fd) { r_socket_free (rtr_host[i].fd); rtr_host[i].fd = NULL; if (rtr_n == i) for (rtr_n = 0; !rtr_host[rtr_n].fd && rtr_n < RTR_MAX_HOSTS; rtr_n++); break; } } else { for (i = 0; i < RTR_MAX_HOSTS; i++) if (rtr_host[i].fd) r_socket_free (rtr_host[i].fd); memset (rtr_host, '\0', RTR_MAX_HOSTS * sizeof(RCoreRtrHost)); rtr_n = 0; } }
R_API RAnalVar *get_link_var(RAnal *anal, ut64 faddr, RAnalVar *var) { const char *var_local = sdb_fmt ("var.0x%"PFMT64x".%d.%d.%s", faddr, 1, var->delta, "reads"); const char *xss = sdb_const_get (anal->sdb_fcns, var_local, 0); ut64 addr = r_num_math (NULL, xss); char *inst_key = r_str_newf ("inst.0x%"PFMT64x".lvar", addr); char *var_def = sdb_get (anal->sdb_fcns, inst_key, 0); if (!var_def) { free (inst_key); return NULL; } struct VarUsedType vut; RAnalVar *res = NULL; if (sdb_fmt_tobin (var_def, SDB_VARUSED_FMT, &vut) == 4) { res = r_anal_var_get (anal, vut.fcn_addr, vut.type[0], vut.scope, vut.delta); sdb_fmt_free (&vut, SDB_VARUSED_FMT); } free (inst_key); free (var_def); return res; }
static RIODesc *__open(RIO *io, const char *pathname, int rw, int mode) { if (__check (io, pathname, 0)) { RIOMalloc *mal = R_NEW0 (RIOMalloc); if (!mal) return NULL; rw = 7; // RWX mal->fd = -2; /* causes r_io_desc_new() to set the correct fd */ if (!strncmp (pathname, "hex://", 6)) { mal->size = strlen (pathname); mal->buf = malloc (mal->size + 1); if (!mal->buf) { free (mal); return NULL; } mal->offset = 0; memset (mal->buf, 0, mal->size); mal->size = r_hex_str2bin (pathname + 6, mal->buf); if ((int)mal->size < 1) { R_FREE (mal->buf); } } else { mal->size = r_num_math (NULL, pathname + 9); if (((int)mal->size) <= 0) { free (mal); eprintf ("Cannot allocate (%s) 0 bytes\n", pathname + 9); return NULL; } mal->offset = 0; mal->buf = calloc (1, mal->size + 1); } if (mal->buf) { RETURN_IO_DESC_NEW (&r_io_plugin_malloc, mal->fd, pathname, rw, mode, mal); } eprintf ("Cannot allocate (%s) %d bytes\n", pathname + 9, mal->size); free (mal); } return NULL; }
static int filter(RParse *p, RFlag *f, char *data, char *str, int len) { char *ptr = data, *ptr2; //RListIter *iter; RFlagItem *flag; ut64 off; ptr2 = NULL; while ((ptr = strstr (ptr, "0x"))) { for (ptr2 = ptr; *ptr2 && !isx86separator (*ptr2); ptr2++); off = r_num_math (NULL, ptr); if (!off) { ptr = ptr2; continue; } flag = r_flag_get_i (f, off); if (flag && strchr (flag->name, '.')) { // XXX. tooslow but correct //r_list_foreach (f->flags, iter, flag) { if (flag->offset == off && strchr (flag->name, '.')) { if (p->notin_flagspace != -1) { if (p->flagspace == flag->space) continue; } else if (p->flagspace != -1 && \ (p->flagspace != flag->space)) { continue; } *ptr = 0; snprintf (str, len, "%s%s%s", data, flag->name, ptr2!=ptr? ptr2: ""); return R_TRUE; } //} ptr = ptr2; } strncpy (str, data, len); return R_FALSE; }
static int exprmatchreg (RDebug *dbg, const char *regname, const char *expr) { int ret = 0; char *p; char *s = strdup (expr); if (!s) { return 0; } if (!strcmp (regname, s)) { ret = 1; } else { #define CURVAL 0){}r_str_trim_head_tail (s);if (!strcmp(regname,s) && regval ut64 regval = r_debug_reg_get_err (dbg, regname, NULL, NULL); if (exprtoken (dbg, s, ">=", &p)) { if (CURVAL >= r_num_math (dbg->num, p)) ret = 1; } else if (exprtoken (dbg, s, "<=", &p)) { if (CURVAL <= r_num_math (dbg->num, p)) ret = 1; } else if (exprtoken (dbg, s, "==", &p)) { if (CURVAL <= r_num_math (dbg->num, p)) ret = 1; } else if (exprtoken (dbg, s, "<", &p)) { if (CURVAL < r_num_math (dbg->num, p)) ret = 1; } else if (exprtoken (dbg, s, ">", &p)) { if (CURVAL > r_num_math (dbg->num, p)) ret = 1; } else if (exprtoken (dbg, s, " ", &p)) { r_str_trim_head_tail (s); if (!strcmp (regname, s)) { ut64 num = r_num_math (dbg->num, p); ret = exprmatch (dbg, num, s); } } else { if (!strcmp (regname, s)) { ret = 1; } } } free (s); return ret; }
static ut64 num_callback(RNum *userptr, const char *str, int *ok) { RCore *core = (RCore *)userptr; // XXX ? RAnalFunction *fcn; char *ptr, *bptr, *out; RFlagItem *flag; RIOSection *s; RAnalOp op; ut64 ret = 0; if (ok) *ok = R_FALSE; switch (*str) { case '[': { ut64 n = 0LL; int refsz = (core->assembler->bits & R_SYS_BITS_64)? 8: 4; const char *p = NULL; if (strlen (str)>5) p = strchr (str+5, ':'); // TODO: honor LE if (p) { refsz = atoi (str+1); str = p; } // push state { if (str[0] && str[1]) { const char *q; char *o = strdup (str+1); if (o) { q = r_num_calc_index (core->num, NULL); if (q) { if (r_str_replace_char (o, ']', 0)>0) { n = r_num_math (core->num, o); r_num_calc_index (core->num, q); } } free (o); } } } // pop state if (ok) *ok = 1; ut32 num = 0; switch (refsz) { case 8: case 4: case 2: case 1: (void)r_io_read_at (core->io, n, (ut8*)&num, refsz); r_mem_copyendian ((ut8*)&num, (ut8*)&num, refsz, !core->assembler->big_endian); return num; default: eprintf ("Invalid reference size: %d (%s)\n", refsz, str); return 0LL; } } break; case '$': if (ok) *ok = 1; // TODO: group analop-dependant vars after a char, so i can filter r_anal_op (core->anal, &op, core->offset, core->block, core->blocksize); switch (str[1]) { case '.': // can use pc, sp, a0, a1, ... return r_debug_reg_get (core->dbg, str+2); case 'k': if (str[2]!='{') { eprintf ("Expected '{' after 'k'.\n"); break; } bptr = strdup (str+3); ptr = strchr (bptr, '}'); if (ptr == NULL) { // invalid json free (bptr); break; } *ptr = '\0'; ret = 0LL; out = sdb_querys (core->sdb, NULL, 0, bptr); if (out && *out) { if (strstr (out, "$k{")) { eprintf ("Recursivity is not permitted here\n"); } else { ret = r_num_math (core->num, out); } } free (bptr); free (out); return ret; break; case '{': bptr = strdup (str+2); ptr = strchr (bptr, '}'); if (ptr != NULL) { ut64 ret; ptr[0] = '\0'; ret = r_config_get_i (core->config, bptr); free (bptr); return ret; } free (bptr); break; case 'c': return r_cons_get_size (NULL); case 'r': { int rows; r_cons_get_size (&rows); return rows; } case 'e': return r_anal_op_is_eob (&op); case 'j': return op.jump; case 'p': return r_sys_getpid (); case 'P': return (core->dbg->pid>0)? core->dbg->pid: 0; case 'f': return op.fail; case 'm': return op.ptr; // memref case 'v': return op.val; // immediate value case 'l': return op.size; case 'b': return core->blocksize; case 's': if (core->file) { return r_io_desc_size (core->io, core->file->desc); } return 0LL; case 'w': return r_config_get_i (core->config, "asm.bits") / 8; case 'S': s = r_io_section_vget (core->io, core->offset); return s? (str[2]=='S'? s->size: s->vaddr): 3; case '?': return core->num->value; case '$': return core->offset; case 'o': return r_io_section_vaddr_to_offset (core->io, core->offset); case 'C': return getref (core, atoi (str+2), 'r', R_ANAL_REF_TYPE_CALL); case 'J': return getref (core, atoi (str+2), 'r', R_ANAL_REF_TYPE_CODE); case 'D': return getref (core, atoi (str+2), 'r', R_ANAL_REF_TYPE_DATA); case 'X': return getref (core, atoi (str+2), 'x', R_ANAL_REF_TYPE_CALL); case 'I': fcn = r_anal_get_fcn_in (core->anal, core->offset, 0); return fcn? fcn->ninstr: 0; case 'F': fcn = r_anal_get_fcn_in (core->anal, core->offset, 0); return fcn? fcn->size: 0; } break; default: if (*str>'A') { // NOTE: functions override flags RAnalFunction *fcn = r_anal_fcn_find_name (core->anal, str); if (fcn) { if (ok) *ok = R_TRUE; return fcn->addr; } #if 0 ut64 addr = r_anal_fcn_label_get (core->anal, core->offset, str); if (addr != 0) { ret = addr; } else { ... } #endif if ((flag = r_flag_get (core->flags, str))) { ret = flag->offset; if (ok) *ok = R_TRUE; } } break; }
static int cmd_type(void *data, const char *input) { RCore *core = (RCore*)data; switch (input[0]) { // t [typename] - show given type in C syntax case 's': { char *q, *p, *o, *e; p = o = strdup (input+1); for (;;) { q = strchr (p, ' '); if (q) *q = 0; if (!*p) { p++; continue; } e = strchr (p, '='); if (e) { *e = 0; r_anal_type_set (core->anal, core->offset, p, r_num_math (core->num, e+1)); } else eprintf ("TODO: implement get\n"); if (!q) break; p = q+1; } free (o); } break; case ' ': { char *fmt = r_anal_type_format (core->anal, input +1); if (fmt) { r_cons_printf ("pf %s\n", fmt); free (fmt); } else eprintf ("Cannot find '%s' type\n", input+1); } break; #if 0 // t* - list all types in 'pf' syntax case '*': r_anal_type_list (core->anal, R_ANAL_TYPE_ANY, 1); break; #endif case 0: // TODO: use r_cons here //sdb_list (core->anal->sdb_types); sdb_foreach (core->anal->sdb_types, sdbforcb, core); break; case 'o': if (input[1] == ' ') { const char *filename = input + 2; if (!strcmp (filename, "-")) { char *out, *tmp; tmp = r_core_editor (core, ""); if (tmp) { out = r_parse_c_string (tmp); if (out) { r_cons_strcat (out); sdb_query_lines (core->anal->sdb_types, out); free (out); } free (tmp); } } else { char *out = r_parse_c_file (filename); if (out) { r_cons_strcat (out); sdb_query_lines (core->anal->sdb_types, out); free (out); } //r_anal_type_loadfile (core->anal, filename); } } break; // td - parse string with cparse engine and load types from it case 'd': if (input[1] == '?') { const char * help_message[] = { "Usage:", "td[...]", "", "td", "[string]", "Load types from string", NULL }; r_core_cmd_help(core, help_message); } else if (input[1] == '-') { const char *arg = strchr (input+1, ' '); if (arg) arg++; else arg = input+2; r_anal_type_del (core->anal, arg); } else if (input[1] == ' ') { char tmp[256]; snprintf (tmp, sizeof (tmp), "%s;", input+2); //const char *string = input + 2; //r_anal_str_to_type (core->anal, string); char *out = r_parse_c_string (tmp); if (out) { r_cons_strcat (out); sdb_query_lines (core->anal->sdb_types, out); free (out); } } else { eprintf ("Invalid use of td. See td? for help\n"); } break; // tl - link a type to an address case 'l': if (input[1]=='?') { const char * help_message[] = { "Usage: tl", " [typename|addr] ([addr])@[addr|function]", "", NULL }; r_core_cmd_help(core, help_message); } else if (input[1]) { ut64 addr = r_num_math (core->num, input+2); char *ptr = strchr (input + 2, ' '); if (ptr) { addr = r_num_math (core->num, ptr + 1); *ptr = '\0'; } else addr = core->offset; r_anal_type_link (core->anal, input+2, addr); } else { r_core_cmd0 (core, "t~^link"); } break; case '-': if (input[1] == '?') { const char * help_message[] = { "Usage: t-", " <type>", "Delete type by its name", NULL }; r_core_cmd_help(core, help_message); } else if (input[1]=='*') { eprintf ("TODO\n"); } else { const char *name = input + 1; if (*name==' ') name++; if (*name) { r_anal_type_del (core->anal, name); } else eprintf ("Invalid use of t- . See t-? for help.\n"); } break; // tv - get/set type value linked to a given address case 'f': { ut64 addr; char *fmt, key[128]; const char *type; if (input[1]) { addr = r_num_math (core->num, input+1); } else addr = core->offset; snprintf (key, sizeof (key), "link.%"PFMT64x, addr); type = sdb_const_get (core->anal->sdb_types, key, 0); if (type) { fmt = r_anal_type_format (core->anal, type); r_cons_printf ("struct %s {\n", type); if (fmt) { r_core_cmdf (core, "pf %s @ 0x%08"PFMT64x"\n", fmt, addr); free (fmt); }// else eprintf ("Cannot find '%s' type\n", input+1); r_cons_printf ("}\n"); } } break; case '?': if (input[1]) { sdb_query (core->anal->sdb_types, input+1); } else show_help(core); break; } return R_TRUE; }
// XXX: this is very incomplete. must be updated to handle all format chars int r_print_format_struct_size(const char *f, RPrint *p, int mode) { char *o = strdup(f); char *end = strchr (o, ' '), *args, *fmt = o; int size = 0, tabsize=0, i, idx=0, biggest = 0; if (!end && !(end = strchr (o, '\0'))) return -1; if (*end) { *end = 0; args = strdup (end+1); } else { args = strdup (""); } if (fmt[0] == '0') { mode |= R_PRINT_UNIONMODE; fmt++; } else { mode &= ~R_PRINT_UNIONMODE; } r_str_word_set0 (args); for (i=0; i<strlen (fmt); i++) { if (fmt[i] == '[') { char *end = strchr (fmt+i,']'); if (end == NULL) { eprintf ("No end bracket.\n"); continue; } *end = '\0'; tabsize = r_num_math (NULL, fmt+i+1); *end = ']'; while (fmt[i++]!=']'); } else { tabsize = 1; } switch (fmt[i]) { case 'c': case 'b': case '.': size+=tabsize*1; break; case 'w': size += tabsize*2; break; case 'd': case 'o': case 'i': case 'x': case 'f': case 's': case 't': case ':': size += tabsize*4; break; case 'S': case 'q': size += tabsize*8; break; case 'z': case 'Z': size += tabsize; break; case '*': size += tabsize*4; i++; break; case 'B': case 'E': switch (tabsize) { case 1: size+=1; break; case 2: size+=2; break; case 4: size+=4; break; default: break; } break; case '?': { const char *format = NULL; char *endname = NULL, *structname = NULL; structname = strdup(r_str_word_get0 (args, idx)); if (*structname == '(') { endname = strchr (structname, ')'); } else { eprintf ("Struct name missing (%s)\n", structname); free(structname); break; } if (endname) *endname = '\0'; format = r_strht_get (p->formats, structname+1); free (structname); size += tabsize * r_print_format_struct_size (format, p, mode); } break; // TODO continue list default: break; } idx++; if (mode & R_PRINT_UNIONMODE) { if (size > biggest) biggest = size; size = 0; } } free (o); free (args); if (mode & R_PRINT_UNIONMODE) return biggest; else return size; }
static int cmd_meta_hsdmf (RCore *core, const char *input) { int n, type = input[0]; char *t = 0, *p, name[256]; ut64 addr_end = 0LL, addr = core->offset; switch (input[1]) { case '?': eprintf ("See C?\n"); break; case '-': switch (input[2]) { case '*': core->num->value = r_meta_del (core->anal, input[0], 0, UT64_MAX, NULL); break; case ' ': addr = r_num_math (core->num, input+3); default: core->num->value = r_meta_del (core->anal, input[0], addr, 1, NULL); break; } break; case '*': r_meta_list (core->anal, input[0], 1); break; case '!': { char *out, *comment = r_meta_get_string ( core->anal, R_META_TYPE_COMMENT, addr); out = r_core_editor (core, NULL, comment); if (out) { //r_meta_add (core->anal->meta, R_META_TYPE_COMMENT, addr, 0, out); r_core_cmdf (core, "CC-@0x%08"PFMT64x, addr); //r_meta_del (core->anal->meta, input[0], addr, addr+1, NULL); r_meta_set_string (core->anal, R_META_TYPE_COMMENT, addr, out); free (out); } free (comment); } break; case ' ': case '\0': if (type!='z' && !input[1]) { r_meta_list (core->anal, type, 0); break; } t = strdup (input+2); p = NULL; n = 0; strncpy (name, t, sizeof (name)-1); if (*input != 'C') { n = r_num_math (core->num, t); if (type == 'f') { p = strchr (t, ' '); if (p) n = r_print_format (core->print, addr, core->block, core->blocksize, p+1, -1, NULL, NULL); } if (type == 's') { /* This is kept for compatibility with old projects. * Somewhat broken, but project will get corrected on * save and reload. */ p = strchr (t, ' '); if (p) addr = r_num_math (core->num, p+1); } if (!*t || n>0) { RFlagItem *fi; p = strchr (t, ' '); if (p) { *p = '\0'; strncpy (name, p+1, sizeof (name)-1); } else switch (type) { case 'z': type='s'; case 's': // TODO: filter \n and so on :) strncpy (name, t, sizeof (name)-1); name[sizeof (name)-1] = '\0'; r_core_read_at (core, addr, (ut8*)name, sizeof (name)-1); if (n < sizeof(name)) name[n] = '\0'; else name[sizeof (name)-1] = '\0'; break; default: fi = r_flag_get_i (core->flags, addr); if (fi) strncpy (name, fi->name, sizeof (name)-1); } } else if (n<1) { eprintf ("Invalid length %d\n", n); return R_FALSE; } } if (!n) n++; addr_end = addr + n; r_meta_add (core->anal, type, addr, addr_end, name); free (t); //r_meta_cleanup (core->anal->meta, 0LL, UT64_MAX); break; default: eprintf ("Missing space after CC\n"); break; } return R_TRUE; }
static int cmd_meta(void *data, const char *input) { RCore *core = (RCore*)data; int i; RAnalFunction *f; switch (*input) { case 'j': case '*': r_meta_list (core->anal, R_META_TYPE_ANY, *input); break; case 'L': cmd_meta_lineinfo (core, input + 1); break; case 'C': cmd_meta_comment (core, input); break; case 'h': /* comment */ case 's': /* string */ case 'd': /* data */ case 'm': /* magic */ case 'f': /* formatted */ cmd_meta_hsdmf (core, input); break; case '-': if (input[1]!='*') { i = r_num_math (core->num, input+((input[1]==' ')?2:1)); r_meta_del (core->anal, R_META_TYPE_ANY, core->offset, i, ""); } else r_meta_cleanup (core->anal, 0LL, UT64_MAX); break; case '\0': case '?':{ const char* help_msg[] = { "Usage:", "C[-LCvsdfm?] [...]", " # Metadata management", "C*", "", "list meta info in r2 commands", "C-", " [len] [[@]addr]", "delete metadata at given address range", "CL", "[-][*] [file:line] [addr]", "show or add 'code line' information (bininfo)", "CS", "[-][space]", "manage meta-spaces to filter comments, etc..", "CC", "[-] [comment-text] [@addr]", "add/remove comment", "CC!", " [@addr]", "edit comment with $EDITOR", "CCa", "[-at]|[at] [text] [@addr]", "add/remove comment at given address", "CCu", " [comment-text] [@addr]", "add unique comment", "Cs", "[-] [size] [@addr]", "add string", "Ch", "[-] [size] [@addr]", "hide data", "Cd", "[-] [size] [@addr]", "hexdump data", "Cf", "[-] [sz] [fmt..] [@addr]", "format memory (see pf?)", "Cm", "[-] [sz] [fmt..] [@addr]", "magic parse (see pm?)", NULL}; r_core_cmd_help (core, help_msg); } break; case 'F': f = r_anal_get_fcn_in (core->anal, core->offset, R_ANAL_FCN_TYPE_FCN|R_ANAL_FCN_TYPE_SYM); if (f) r_anal_str_to_fcn (core->anal, f, input+2); else eprintf ("Cannot find function here\n"); break; case 'S': { RSpaces *ms = &core->anal->meta_spaces; /** copypasta from `fs`.. this must be refactorized to be shared */ switch (input[1]) { case '?': { const char *help_msg[] = { "Usage: CS","[*] [+-][metaspace|addr]", " # Manage metaspaces", "CS","","display metaspaces", "CS"," *","select all metaspaces", "CS"," metaspace","select metaspace or create if it doesn't exist", "CS","-metaspace","remove metaspace", "CS","-*","remove all metaspaces", "CS","+foo","push previous metaspace and set", "CS","-","pop to the previous metaspace", // "CSm"," [addr]","move metas at given address to the current metaspace", "CSr"," newname","rename selected metaspace", NULL}; r_core_cmd_help (core, help_msg); } break; case '+': r_space_push (ms, input+2); break; case 'r': if (input[2]==' ') r_space_rename (ms, NULL, input+2); else eprintf ("Usage: CSr [newname]\n"); break; case '-': if (input[2]) { if (input[2]=='*') { r_space_unset (ms, NULL); } else { r_space_unset (ms, input+2); } } else { r_space_pop (ms); } break; case 'j': case '\0': case '*': r_space_list (ms, input[1]); break; case ' ': r_space_set (ms, input+2); break; #if 0 case 'm': { RFlagItem *f; ut64 off = core->offset; if (input[2] == ' ') off = r_num_math (core->num, input+2); f = r_flag_get_i (core->flags, off); if (f) { f->space = core->flags->space_idx; } else eprintf ("Cannot find any flag at 0x%"PFMT64x".\n", off); } break; #endif default: { int i, j = 0; for (i=0; i<R_FLAG_SPACES_MAX; i++) { if (ms->spaces[i]) r_cons_printf ("%02d %c %s\n", j++, (i==ms->space_idx)?'*':' ', ms->spaces[i]); } } break; } } break; } return R_TRUE; }
static int cmd_meta_comment(RCore *core, const char *input) { ut64 addr = core->offset; switch (input[1]) { case '?': { const char* help_msg[] = { "Usage:", "CC[-+!*au] [base64:..|str] @ addr", "", "CC", "", "list all comments in human friednly form", "CC*", "", "list all comments in r2 commands", "CC.", "", "show comment at current offset", "CC", " or maybe not", "append comment at current address", "CC+", " same as above", "append comment at current address", "CC!", "", "edit comment using cfg.editor (vim, ..)", "CC-", " @ cmt_addr", "remove comment at given address", "CCu", " good boy @ addr", "add good boy comment at given address", "CCu", " base64:AA== @ addr", "add comment in base64", NULL}; r_core_cmd_help (core, help_msg); } break; case '.': { char *comment = r_meta_get_string ( core->anal, R_META_TYPE_COMMENT, addr); if (comment) { r_cons_printf ("%s\n", comment); free (comment); } } break; case 0: r_meta_list (core->anal, R_META_TYPE_COMMENT, 0); break; case '!': { char *out, *comment = r_meta_get_string ( core->anal, R_META_TYPE_COMMENT, addr); out = r_core_editor (core, NULL, comment); if (out) { //r_meta_add (core->anal->meta, R_META_TYPE_COMMENT, addr, 0, out); r_core_cmdf (core, "CC-@0x%08"PFMT64x, addr); //r_meta_del (core->anal->meta, input[0], addr, addr+1, NULL); r_meta_set_string (core->anal, R_META_TYPE_COMMENT, addr, out); free (out); } free (comment); } break; case '+': case ' ': { const char* newcomment = input+2; char *text, *nc; while (*newcomment==' ') newcomment++; char *comment = r_meta_get_string ( core->anal, R_META_TYPE_COMMENT, addr); nc = strdup (newcomment); r_str_unescape (nc); if (comment) { text = malloc (strlen (comment)+strlen (newcomment)+2); strcpy (text, comment); strcat (text, "\n"); strcat (text, nc); r_meta_set_string (core->anal, R_META_TYPE_COMMENT, addr, text); free (text); } else { r_meta_set_string (core->anal, R_META_TYPE_COMMENT, addr, nc); } free (nc); } break; case '*': r_meta_list (core->anal, R_META_TYPE_COMMENT, 1); break; case '-': r_meta_del (core->anal, R_META_TYPE_COMMENT, core->offset, 1, NULL); break; case 'u': // { char *newcomment; const char *arg = input+2; while (*arg && *arg == ' ') arg++; if (!strncmp (arg, "base64:", 7)) { char *s = (char *)sdb_decode (arg+7, NULL); if (s) { newcomment = s; } else { newcomment = NULL; } } else { newcomment = strdup (arg); } if (newcomment) { char *comment = r_meta_get_string ( core->anal, R_META_TYPE_COMMENT, addr); if (!comment || (comment && !strstr (comment, newcomment))) { r_meta_set_string (core->anal, R_META_TYPE_COMMENT, addr, newcomment); } free (comment); free (newcomment); } } break; case 'a': { char *s, *p; s = strchr (input, ' '); if (s) { s = strdup (s+1); } else { eprintf ("Usage\n"); return R_FALSE; } p = strchr (s, ' '); if (p) *p++ = 0; ut64 addr; if (input[2]=='-') { if (input[3]) { addr = r_num_math (core->num, input+3); r_meta_del (core->anal, R_META_TYPE_COMMENT, addr, 1, NULL); } else eprintf ("Usage: CCa-[address]\n"); free (s); return R_TRUE; } addr = r_num_math (core->num, s); // Comment at if (p) { if (input[2]=='+') { char *text = p; char *comment = r_meta_get_string ( core->anal, R_META_TYPE_COMMENT, addr); if (comment) { text = malloc (strlen (comment) + strlen (p)+2); strcpy (text, comment); strcat (text, "\n"); strcat (text, p); r_meta_add (core->anal, R_META_TYPE_COMMENT, addr, addr+1, text); free (text); } else { r_meta_add (core->anal, R_META_TYPE_COMMENT, addr, addr+1, p); } } else { r_meta_add (core->anal, R_META_TYPE_COMMENT, addr, addr+1, p); } } else eprintf ("Usage: CCa [address] [comment]\n"); free (s); return R_TRUE; } } return R_TRUE; }
static int cmd_meta_lineinfo(RCore *core, const char *input) { int ret; ut64 offset = UT64_MAX; // use this as error value int remove = R_FALSE; int all = R_FALSE; const char *p = input; char *colon, *space, *file_line = 0; if (*p == '?') { eprintf ("Usage: CL[-][*] [file:line] [addr]"); return 0; } if (*p == '-') { p++; remove = R_TRUE; } if (*p == '*') { p++; all = R_TRUE; } if (all) { if (remove) { sdb_reset (core->bin->cur->sdb_addrinfo); } else { sdb_foreach (core->bin->cur->sdb_addrinfo, print_addrinfo, NULL); } return 0; } while (*p == ' ') { p++; } if (*p) { offset = r_num_math (core->num, p); if (!offset) offset = core->offset; } else offset = core->offset; colon = strchr (p, ':'); if (colon) { space = strchr (p, ' '); if (!space) { file_line = strdup (p); } else if (space > colon) { file_line = r_str_ndup (p, space - p); } else { goto error; } colon = strchr (file_line, ':'); if (!colon) goto error; *colon = '|'; while (*p != ' ') p++; while (*p == ' ') p++; if (*p != '\0') { ret = sscanf (p, "0x%"PFMT64x, &offset); if (ret != 1) { eprintf ("Failed to parse addr at %s\n", p); goto error; } ret = cmd_meta_add_fileline (core->bin->cur->sdb_addrinfo, file_line, offset); goto error; } if (!file_line) return -1; if (remove) { remove_meta_fileline (core, file_line); } else { print_meta_fileline (core, file_line); } free (file_line); return 0; } offset = core->offset; if (offset != UT64_MAX) { if (remove) { remove_meta_offset (core, offset); } else { print_meta_offset (core, offset); } } else { goto error; } return 0; error: free (file_line); return -1; }
static void cmd_write_op (RCore *core, const char *input) { ut8 *buf; int len; int value; if (!input[0]) return; switch (input[1]) { case 'e': if (input[2]!=' ') { r_cons_printf ("Usage: 'woe from-to step'\n"); return; } /* fallthru */ case 'a': case 's': case 'A': case 'x': case 'r': case 'l': case 'm': case 'd': case 'o': case 'w': case '2': case '4': if (input[2]) { // parse val from arg r_core_write_op (core, input+3, input[1]); r_core_block_read (core); } else { // use clipboard instead of val r_core_write_op (core, NULL, input[1]); r_core_block_read (core); } break; case 'R': r_core_cmd0 (core, "wr $b"); break; case 'n': r_core_write_op (core, "ff", 'x'); r_core_block_read (core); break; case 'E': // "woE" encrypt case 'D': // "woD" decrypt { int direction = (input[1] == 'E') ? 0 : 1; const char *algo = NULL; const char *key = NULL; const char *iv = NULL; char *space, *args = strdup (r_str_trim_ro (input+2)); space = strchr (args, ' '); if (space) { *space++ = 0; key = space; space = strchr (key, ' '); if (space) { *space++ = 0; iv = space; } } algo = args; if (algo && *algo && key) { encrypt_or_decrypt_block (core, algo, key, direction, iv); } else { eprintf ("Usage: wo%c [algo] [key] [IV]\n", ((!direction)?'E':'D')); eprintf ("Currently supported hashes:\n"); ut64 bits; int i; for (i = 0; ; i++) { bits = ((ut64)1) << i; const char *name = r_hash_name (bits); if (!name || !*name) break; printf (" %s\n", name); } eprintf ("Available Encoders/Decoders: \n"); // TODO: do not hardcode eprintf (" base64\n"); eprintf (" base91\n"); eprintf (" punycode\n"); eprintf ("Currently supported crypto algos:\n"); for (i = 0; ; i++) { bits = ((ut64)1) << i; const char *name = r_crypto_name (bits); if (!name || !*name) break; printf (" %s\n", name); } } free (args); } break; case 'p': // debrujin patterns switch (input[2]) { case 'D': // "wopD" len = (int)(input[3]==' ') ? r_num_math (core->num, input + 3) : core->blocksize; if (len > 0) { /* XXX This seems to fail at generating long patterns (wopD 512K) */ buf = (ut8*)r_debruijn_pattern (len, 0, NULL); //debruijn_charset); if (buf) { const ut8 *ptr = buf; ut64 addr = core->offset; if (input[3] == '*') { int i; r_cons_printf ("wx "); for (i = 0; i < len; i++) { r_cons_printf ("%02x", buf[i]); } r_cons_newline (); } else { while (true) { int res = r_core_write_at (core, addr, ptr, len); if (res < 1 || len == res) { break; } if (res < len) { ptr += res; len -= res; addr += res; } } } free (buf); } else { eprintf ("Couldn't generate pattern of length %d\n", len); } } break; case 'O': // "wopO" if (strlen (input) > 4 && strncmp (input + 4, "0x", 2)) { eprintf ("Need hex value with `0x' prefix e.g. 0x41414142\n"); } else if (input[3] == ' ') { value = r_num_get (core->num, input + 4); core->num->value = r_debruijn_offset (value, r_config_get_i (core->config, "cfg.bigendian")); r_cons_printf ("%"PFMT64d"\n", core->num->value); } break; case '\0': case '?': default: r_core_cmd_help (core, help_msg_wop); break; } break; case '\0': case '?': default: r_core_cmd_help (core, help_msg_wo); break; } }
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 void cmd_write_value (RCore *core, const char *input) { int type = 0; ut64 off = 0LL; ut8 buf[sizeof(ut64)]; int wseek = r_config_get_i (core->config, "cfg.wseek"); bool be = r_config_get_i (core->config, "cfg.bigendian"); if (!input) return; if (input[0]) switch (input[1]) { case '?': r_core_cmd_help (core, help_msg_wv); return; case '1': type = 1; break; case '2': type = 2; break; case '4': type = 4; break; case '8': type = 8; break; } if (input && input[0] && input[1] && input[2]) { off = r_num_math (core->num, input+2); } if (core->file) { r_io_use_fd (core->io, core->file->fd); } ut64 res = r_io_seek (core->io, core->offset, R_IO_SEEK_SET); if (res == UT64_MAX) return; if (type == 0) type = (off&UT64_32U)? 8: 4; switch (type) { case 1: r_write_ble8 (buf, (ut8)(off & UT8_MAX)); if (!r_io_write (core->io, buf, 1)) { cmd_write_fail (); } else { WSEEK (core, 1); } break; case 2: r_write_ble16 (buf, (ut16)(off & UT16_MAX), be); if (!r_io_write (core->io, buf, 2)) { cmd_write_fail (); } else { WSEEK (core, 2); } break; case 4: r_write_ble32 (buf, (ut32)(off & UT32_MAX), be); if (!r_io_write (core->io, buf, 4)) { cmd_write_fail (); } else { WSEEK (core, 4); } break; case 8: r_write_ble64 (buf, off, be); if (!r_io_write (core->io, buf, 8)) { cmd_write_fail (); } else { WSEEK (core, 8); } break; } r_core_block_read (core); }
R_API int r_print_format(RPrint *p, ut64 seek, const ut8* b, const int len, const char *fmt, int mode, const char *setval, char *ofield) { int nargs, i, j, invalid, nexti, idx, times, otimes, endian, isptr = 0; const char *argend; ut64 addr = 0, addr64 = 0, seeki = 0;; char *args = NULL, *bracket, tmp, last = 0; const char *arg = fmt; int viewflags = 0; char namefmt[8], *field = NULL; static int slide=0, oldslide=0; ut8 *buf; if (!fmt) return 0; argend = fmt+strlen (fmt); nexti = nargs = i = j = 0; if (len < 1) return 0; buf = malloc (len); if (!buf) return 0; memcpy (buf, b, len); endian = p->big_endian; if (ofield && ofield != MINUSONE) field = strdup (ofield); while (*arg && iswhitechar (*arg)) arg++; /* get times */ otimes = times = atoi (arg); if (times > 0) while ((*arg>='0'&&*arg<='9')) arg++; bracket = strchr (arg,'{'); if (bracket) { char *end = strchr (arg, '}'); if (end == NULL) { eprintf ("No end bracket. Try pm {ecx}b @ esi\n"); goto beach; } *end='\0'; times = r_num_math (NULL, bracket+1); arg = end + 1; } if (*arg=='\0') { goto beach; } /* get args */ args = strchr (arg, ' '); if (args) { int l=0, maxl = 0; argend = args; args = strdup (args+1); nargs = r_str_word_set0 (args); if (nargs == 0) R_FREE (args); for (i=0; i<nargs; i++) { const int len = strlen (r_str_word_get0 (args, i)); if (len > maxl) maxl = len; } l++; snprintf (namefmt, sizeof (namefmt), "%%%ds : ", maxl+6*slide%STRUCTPTR); } #define ISPOINTED ((slide%STRUCTFLAG)/STRUCTPTR<=(oldslide%STRUCTFLAG)/STRUCTPTR) #define ISNESTED ((slide%STRUCTPTR)<=(oldslide%STRUCTPTR)) if (mode == R_PRINT_JSON && slide==0) p->printf("["); if (arg[0] == '0') { mode |= R_PRINT_UNIONMODE; arg++; } else { mode &= ~R_PRINT_UNIONMODE; } /* go format */ i = 0; if (!times) otimes = times = 1; for (; times; times--) { // repeat N times const char * orig = arg; int first = 1; if (otimes>1) { if (mode & R_PRINT_JSON) { if (otimes > times) p->printf (","); p->printf ("[{\"index\":%d,\"offset\":%d},", otimes-times, seek+i); } else p->printf ("0x%08"PFMT64x" [%d] {\n", seek+i, otimes-times); } arg = orig; for (idx=0; i<len && arg<argend && *arg; arg++) { int size, elem; /* size of the array, element of the array */ char *fieldname = NULL, *fmtname = NULL, *oarg = NULL; if (mode & R_PRINT_UNIONMODE) { i = 0; } seeki = seek+i; addr = 0LL; invalid = 0; if (arg[0] == '[') { char *end = strchr (arg,']'); if (end == NULL) { eprintf ("No end bracket.\n"); goto beach; } *end = '\0'; size = r_num_math (NULL, arg+1); arg = end + 1; *end = ']'; } else { size = -1; } updateAddr (buf, i, endian, &addr, &addr64); tmp = *arg; if (args == NULL) mode |= R_PRINT_ISFIELD; if (mode & R_PRINT_MUSTSEE && otimes>1) p->printf (" "); if (idx<nargs && tmp != 'e' && isptr == 0) { char *dot = NULL, *bracket = NULL; if (field) dot = strchr (field, '.'); if (dot) *dot = '\0'; oarg = fieldname = strdup(r_str_word_get0 (args, idx)); if (ISSTRUCT || tmp=='E' || tmp=='B') { if (*fieldname == '(') { fmtname = fieldname+1; fieldname = strchr (fieldname, ')'); if (fieldname) *fieldname++ = '\0'; else { eprintf ("Missing closing parenthesis in format ')'\n"); free (oarg); goto beach; } } else { eprintf ("Missing name (%s)\n", fieldname); free(oarg); goto beach; } } if (args == NULL || (field==NULL && ofield != MINUSONE) || (field && !strncmp(field, fieldname, strlen(fieldname)))) { mode |= R_PRINT_ISFIELD; } else { mode &= ~R_PRINT_ISFIELD; } /* There we handle specific element in array */ if (field != NULL && (bracket = strchr (field, '[')) != NULL && mode & R_PRINT_ISFIELD) { char *end = strchr (field, ']'); if (end == NULL) { eprintf ("Missing closing bracket\n"); goto beach; } *end = '\0'; elem = r_num_math (NULL, bracket+1)+1; // +1 to handle 0 index easily for ( ; bracket < end; bracket++) *bracket = '\0'; size += elem*ARRAYINDEX_COEF; } else { elem = -1; } idx++; if (MUSTSEE) { p->printf (namefmt, fieldname); } } feed_me_again: switch (isptr) { case 1: { nexti = i + (p->bits/8); i = 0; if(tmp == '?' )seeki = addr; memset (buf, '\0', len); if (MUSTSEE) p->printf ("(*0x%"PFMT64x") ", addr); if (addr == 0) isptr = NULLPTR; else isptr = PTRBACK; if (/*addr<(b+len) && addr>=b && */p->iob.read_at) { /* The test was here to avoid segfault in the next line, but len make it doesnt work... */ p->iob.read_at (p->iob.io, (ut64)addr, buf, len-4); updateAddr (buf, i, endian, &addr, &addr64); } else { eprintf ("(SEGFAULT: cannot read memory at 0x%08"PFMT64x", Block: %s, blocksize: 0x%x)\n", addr, b, len); p->printf("\n"); free (oarg); goto beach; } } break; case 2: // restore state after pointer seek i = nexti; seeki = seek+i; memcpy (buf, b, len); isptr = NOPTR; arg--; continue; } if (tmp == 0 && last != '*') break; /* skip chars */ switch (tmp) { case '*': // next char is a pointer isptr = PTRSEEK; arg++; tmp = *arg; //last; goto feed_me_again; case '+': // toggle view flags viewflags = !viewflags; continue; case 'e': // tmp swap endian endian ^= 1; continue; case ':': // skip 4 bytes if (size == -1) i+=4; else while (size--) i+=4; continue; case '.': // skip 1 byte if (size == -1) i++; else i+=size; continue; case 'p': // pointer reference tmp = (p->bits == 64)? 'q': 'x'; break; } /* flags */ if (mode & R_PRINT_SEEFLAGS && isptr != NULLPTR) { if (tmp == '?') { p->printf ("f %s.%s_", fmtname, fieldname); } else if (tmp == 'E') { p->printf ("f %s=0x%08"PFMT64x"\n", fieldname, seeki); } else if (slide/STRUCTFLAG>0 && idx==1) { p->printf ("%s=0x%08"PFMT64x"\n", fieldname, seeki); } else p->printf ("f %s=0x%08"PFMT64x"\n", fieldname , seeki); } /* json */ if (mode & R_PRINT_JSON) { if (oldslide<=slide) { if (!first) p->printf (","); else first = 0; } else if(oldslide!=0) { p->printf ("]},"); } p->printf ("{\"name\":\"%s\",\"type\":\"", fieldname); if (ISSTRUCT) { p->printf ("%s", fmtname); } else { p->printf ("%c", tmp); } if (isptr) p->printf ("*"); p->printf ("\",\"offset\":%d,\"value\":",(isptr)?(seek+nexti-(p->bits/8)):seek+i); } if (isptr == NULLPTR) { if (MUSTSEEJSON) p->printf ("\"NULL\"}", tmp, seek+i); else if (MUSTSEE) p->printf ("NULL\n"); isptr = PTRBACK; } else /* format chars */ switch (tmp) { case 't': r_print_format_time(p, endian, mode, setval, seeki, buf, i, size); i+= (size==-1) ? 4 : 4*size; break; case 'q': r_print_format_quadword(p, endian, mode, setval, seeki, buf, i, size); i += (size==-1) ? 8 : 8*size; break; case 'b': r_print_format_byte(p, endian, mode, setval, seeki, buf, i, size); i+= (size==-1) ? 1 : size; break; case 'c': r_print_format_char (p, endian, mode, setval, seeki, buf, i, size); i+= (size==-1) ? 1 : size; break; case 'X': size = r_print_format_hexpairs (p, endian, mode, setval, seeki, buf, size); i += size; break; case 'T': if(r_print_format_10bytes(p, mode, setval, seeki, addr, buf) == 0) i += (size==-1) ? 4 : 4*size; break; case 'f': r_print_format_float(p, endian, mode, setval, seeki, buf, i, size); i += (size==-1) ? 4 : 4*size; break; case 'i': case 'd': r_print_format_hex(p, endian, mode, setval, seeki, buf, i, size); i+= (size==-1) ? 4 : 4*size; break; case 'D': if (size>0) p->printf ("Size not yet implemented\n"); if (p->disasm && p->user) i += p->disasm (p->user, seeki); break; case 'o': r_print_format_octal (p, endian, mode, setval, seeki, buf, i, size); i+= (size==-1) ? 4 : 4*size; break; case 'x': r_print_format_hexflag(p, endian, mode, setval, seeki, buf, i, size); i+= (size==-1) ? 4 : 4*size; break; case 'w': r_print_format_word(p, endian, mode, setval, seeki, buf, i, size); i+= (size==-1) ? 2 : 2*size; break; case 'z': // zero terminated string r_print_format_nulltermstring (p, len, endian, mode, setval, seeki, buf, i, size); if (size == -1) i+=strlen((char*)buf+i)+1; else while (size--) i++; break; case 'Z': // zero terminated wide string r_print_format_nulltermwidestring (p, len, endian, mode, setval, seeki, buf, i, size); if (size == -1) i+=r_wstr_clen((char*)(buf+seeki))*2+2; else while (size--) i+=2; break; case 's': if (r_print_format_string (p, seeki, addr64, addr, 0, mode) == 0) i += (size==-1) ? 4 : 4*size; break; case 'S': if (r_print_format_string (p, seeki, addr64, addr, 1, mode) == 0) i += (size==-1) ? 8 : 8*size; break; case 'B': // resolve bitfield if (size >= ARRAYINDEX_COEF) size %= ARRAYINDEX_COEF; r_print_format_bitfield (p, seeki, fmtname, fieldname, addr, mode, size); i+=(size==-1)?1:size; break; case 'E': // resolve enum if (size >= ARRAYINDEX_COEF) size %= ARRAYINDEX_COEF; r_print_format_enum (p, seeki, fmtname, fieldname, addr, mode, size); i+=(size==-1)?1:size; break; case '?': { int s = 0; char *nxtfield = NULL; if (size >= ARRAYINDEX_COEF) { elem = size/ARRAYINDEX_COEF-1; size %= ARRAYINDEX_COEF; } if (!(mode & R_PRINT_ISFIELD)) nxtfield = MINUSONE; else if (field) nxtfield = strchr (ofield, '.'); if (nxtfield != MINUSONE && nxtfield != NULL) nxtfield++; if (MUSTSEE) p->printf ("\n"); if (MUSTSEEJSON) { if (isptr) p->printf ("%d},", seeki); else p->printf ("["); } if (mode & R_PRINT_SEEFLAGS) slide+=STRUCTFLAG; oldslide = slide; slide += (isptr) ? STRUCTPTR : NESTEDSTRUCT; if (size == -1) { s = r_print_format_struct (p, seeki, buf+i, len-i, fmtname, slide, mode, setval, nxtfield); i+= (isptr) ? 4 : s; } else { p->printf ("[\n"); while (size--) { if (elem == -1 || elem == 0) { mode |= R_PRINT_MUSTSEE; if (elem == 0) elem = -2; } else { mode &= ~R_PRINT_MUSTSEE; } s = r_print_format_struct (p, seek+i, buf+i, len-i, fmtname, slide, mode, setval, nxtfield); if (size != 0 && elem == -1) p->printf (",\n"); if (elem > -1) elem--; i+= (isptr) ? 4 : s; } if (MUSTSEEJSON) p->printf ("]]}"); else p->printf ("]"); } oldslide = slide; slide -= (isptr) ? STRUCTPTR : NESTEDSTRUCT; if (mode & R_PRINT_SEEFLAGS) { oldslide = slide; slide-=STRUCTFLAG; } break; } default: /* ignore unknown chars */ invalid = 1; break; } if (viewflags && p->offname) { const char *s = p->offname (p->user, seeki); if (s) p->printf ("@(%s)", s); s = p->offname (p->user, addr); if (s) p->printf ("*(%s)", s); } if (tmp != 'D' && !invalid && fmtname==NULL && MUSTSEE) p->printf ("\n"); last = tmp; if (oarg) free (oarg); } if (otimes>1) { if (MUSTSEEJSON) p->printf ("]"); else p->printf ("}\n"); } arg = orig; oldslide = 0; } if (mode & R_PRINT_JSON && slide==0) p->printf("]"); beach: free (buf); free (field); if (args) free (args); return i; }
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); } }