SDB_API char *sdb_array_pop(Sdb *s, const char *key, ut32 *cas) { ut32 kas; char *end, *str = sdb_get (s, key, &kas); if (!str || !*str) { free (str); return NULL; } if (cas && *cas != kas) *cas = kas; #if PUSH_PREPENDS end = strchr (str, SDB_RS); if (end) { *end = 0; sdb_set (s, key, end+1, 0); } else { sdb_unset (s, key, 0); } return str; #else for (end = str+strlen (str)-1; end>str && *end!=SDB_RS; end--); if (*end==SDB_RS) *end++ = 0; sdb_set_owned (s, key, str, 0); // XXX: probably wrong return strdup (end); #endif }
R_API char *r_type_link_at (Sdb *TDB, ut64 addr) { char* res = NULL; if (addr == UT64_MAX) { return NULL; } char* query = sdb_fmt ("link.%08"PFMT64x, addr); res = sdb_get (TDB, query, 0); if (!res) { // resolve struct memb if possible for given addr SdbKv *kv; SdbListIter *sdb_iter; SdbList *sdb_list = sdb_foreach_list (TDB, true); ls_foreach (sdb_list, sdb_iter, kv) { if (strncmp (kv->key, "link.", strlen ("link."))) { continue; } const char *linkptr = sdb_fmt ("0x%s", kv->key + strlen ("link.")); ut64 baseaddr = r_num_math (NULL, linkptr); int delta = (addr > baseaddr)? addr - baseaddr: -1; res = r_type_get_struct_memb (TDB, kv->value, delta); if (res) { break; } } ls_free (sdb_list); }
static void runline (Sdb *s, const char *cmd) { ut64 n; char *p, *eq; switch (*cmd) { case '+': // inc n = sdb_inc (s, cmd, 1); save = 1; printf ("%"ULLFMT"d\n", n); break; case '-': // dec n = sdb_inc (s, cmd, -1); save = 1; printf ("%"ULLFMT"d\n", n); break; default: if ((eq = strchr (cmd, '='))) { save = 1; *eq = 0; sdb_set (s, cmd, eq+1); } else if ((p = sdb_get (s, cmd))) { printf ("%s\n", p); free (p); } } }
SDB_API int sdb_array_delete(Sdb *s, const char *key, int idx, ut32 cas) { int i; char *p, *n, *str = sdb_get (s, key, 0); p = str; if (!str || !*str) { free (str); return 0; } if (idx < 0) { idx = sdb_alen (str); if (idx) idx--; } for (i = 0; i < idx; i++) { if ( (n = strchr (p, SDB_RS)) ) { p = n + 1; } else { free (str); return 0; } } n = strchr (p, SDB_RS); if (n) { memmove (p, n + 1, strlen (n)); } else { if (p != str) p--; // remove tailing SDB_RS *p = 0; p[1] = 0; } sdb_set_owned (s, key, str, cas); return 1; }
R_API RAnalVar *r_anal_var_get (RAnal *a, ut64 addr, char kind, int scope, int delta) { RAnalVar *av; struct VarType vt; RAnalFunction *fcn = r_anal_get_fcn_in (a, addr, 0); if (!fcn) return NULL; if (delta<0) { kind = 'v'; delta = -delta; } char *vardef = sdb_get (DB, sdb_fmt (0, "var.0x%"PFMT64x".%c.%d.%d", fcn->addr, kind, scope, delta), 0); if (!vardef) return NULL; sdb_fmt_tobin (vardef, SDB_VARTYPE_FMT, &vt); av = R_NEW0 (RAnalVar); av->addr = addr; av->scope = scope; av->delta = delta; av->name = strdup (vt.name); av->size = vt.size; av->type = strdup (vt.type); sdb_fmt_free (&vt, SDB_VARTYPE_FMT); // TODO: // get name from sdb // get size from sdb // get type from sdb return av; }
R_API int r_anal_xrefs_from (RAnal *anal, RList *list, const char *kind, const RAnalRefType type, ut64 addr) { char *next, *s, *str, *ptr, key[256]; RAnalRef *ref = NULL; if (addr == UT64_MAX) { _type = type; _list = list; _kpfx = r_str_newf ("xref.%s", analref_toString (type)); sdb_foreach (DB, (SdbForeachCallback)xrefs_list_cb_any, anal); free (_kpfx); return true; } XREFKEY(key, sizeof (key), kind, type, addr); str = sdb_get (DB, key, 0); if (!str) { return false; } for (next = ptr = str; next; ptr = next) { s = sdb_anext (ptr, &next); if (!(ref = r_anal_ref_new ())) { return false; } ref->addr = r_num_get (NULL, s); ref->at = addr; ref->type = type; r_list_append (list, ref); } free (str); return true; }
static int typelist (void *p, const char *k, const char *v) { r_cons_printf ("tk %s = %s\n", k, v); #if 0 if (!strcmp (v, "func")) { const char *rv = sdb_const_get (DB, sdb_fmt (0, "func.%s.ret", k), 0); r_cons_printf ("# %s %s(", rv, k); for (i = 0; i < 16; i++) { char *av = sdb_get (DB, sdb_fmt (0, "func.%s.arg.%d", k, i), 0); if (!av) break; r_str_replace_char (av, ',', ' '); r_cons_printf ("%s%s", i? ", ": "", av); free (av); } r_cons_printf (");\n"); // signature in pf for asf r_cons_printf ("asf %s=", k); // formats for (i = 0; i < 16; i++) { const char *fmt; char *comma, *av = sdb_get (DB, sdb_fmt (0, "func.%s.arg.%d", k, i), 0); if (!av) break; comma = strchr (av, ','); if (comma) *comma = 0; fmt = sdb_const_get (DB, sdb_fmt (0, "type.%s", av), 0); r_cons_printf ("%s", fmt); if (comma) *comma = ','; free (av); } // names for (i = 0; i < 16; i++) { char *comma, *av = sdb_get (DB, sdb_fmt (0, "func.%s.arg.%d", k, i), 0); if (!av) break; comma = strchr (av, ','); if (comma) *comma++ = 0; r_cons_printf (" %s", comma); free (av); } r_cons_newline (); } #endif return 1; }
SDB_API int sdb_json_geti (Sdb *s, const char *k, const char *p, ut32 *cas) { char *v = sdb_get (s, k, cas); if (v) { Rangstr rs = json_get (v, p); return rangstr_int (&rs); } return 0; }
SDB_VISIBLE int sdb_json_geti (Sdb *s, const char *k, const char *p) { char *v = sdb_get (s, k, 0); // XXX cas if (v) { Rangstr rs = json_get (v, p); return rangstr_int (&rs); } return 0; }
static int print_meta_fileline(RCore *core, const char *file_line) { char *meta_info = sdb_get (core->bin->cur->sdb_addrinfo, file_line, 0); if (meta_info) { r_cons_printf ("Meta info %s\n", meta_info); } else { r_cons_printf ("No meta info for %s found\n", file_line); } return 0; }
SDB_API char *sdb_json_get (Sdb *s, const char *k, const char *p, ut32 *cas) { Rangstr rs; char *u, *v = sdb_get (s, k, cas); if (!v) return NULL; rs = json_get (v, p); u = rangstr_dup (&rs); free (v); return u; }
R_API RSyscallItem *r_syscall_get(RSyscall *s, int num, int swi) { char *ret, *ret2, foo[32]; RSyscallItem *si; if (!s || !s->db) return NULL; swi = getswi (s->db, swi); snprintf (foo, sizeof (foo), "0x%02x.%d", swi, num); ret = sdb_get (s->db, foo, 0); if (ret == NULL) return NULL; // TODO: optimize with sdb_const_get ret2 = sdb_get (s->db, ret, 0); if (ret2 == NULL) return NULL; si = r_syscall_item_new_from_string (ret, ret2); free (ret); free (ret2); return si; }
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 char *r_type_enum_member(Sdb *TDB, const char *name, const char *member, ut64 val) { const char *q; if (r_type_kind (TDB, name) != R_TYPE_ENUM) { return NULL; } if (member) { q = sdb_fmt ("enum.%s.%s", name, member); } else { q = sdb_fmt ("enum.%s.0x%x", name, val); } return sdb_get (TDB, q, 0); }
R_API int r_meta_del(RAnal *a, int type, ut64 addr, ut64 size, const char *str) { char key[100], *dtr, *s, *p, *next; #if 0 char key2[100]; #endif const char *ptr; int i; if (size == UT64_MAX) { // FULL CLEANUP // XXX: this thing ignores the type if (type == R_META_TYPE_ANY) { sdb_reset (DB); } else { snprintf (key, sizeof (key)-1, "meta.%c.count", type); int last = (ut64)sdb_num_get (DB, key, NULL)/K; for (i=0; i<last; i++) { snprintf (key, sizeof (key)-1, "meta.%c.%d", type, i); dtr = sdb_get (DB, key, 0); for (p = dtr; p; p = next) { s = sdb_anext (p, &next); snprintf (key, sizeof (key)-1, "meta.%c.0x%"PFMT64x, type, sdb_atoi (s)); eprintf ("--> %s\n", key); sdb_unset (DB, key, 0); if (!next) break; } free (dtr); } } return false; } meta_inrange_del (a, addr, size); snprintf (key, sizeof (key)-1, type == R_META_TYPE_COMMENT ? "meta.C.0x%"PFMT64x : "meta.0x%"PFMT64x, addr); ptr = sdb_const_get (DB, key, 0); if (ptr) { sdb_unset (DB, key, 0); #if 0 // This code is wrong, but i guess it's necessary in case type is ANY for (i=0; ptr[i]; i++) { if (ptr[i] != SDB_RS) { snprintf (key2, sizeof (key2)-1, "meta.%c.0x%"PFMT64x, ptr[i], addr); printf ("UNSET (%s)\n", key2); sdb_unset (DB, key2, 0); } } #endif } sdb_unset (DB, key, 0); return false; }
static RAnalVar *get_used_var(RAnal *anal, RAnalOp *op) { char *inst_key = r_str_newf ("inst.0x%"PFMT64x".vars", op->addr); char *var_def = sdb_get (anal->sdb_fcns, inst_key, 0); 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; }
R_API int r_syscall_get_num(RSyscall *s, const char *str) { char *o; int i = -1; // TODO: use sdb array api here if (!s || !s->db) return -1; o = sdb_get (s->db, str, 0); if (o && *o) { r_str_split (o, ','); i = r_num_get (NULL, r_str_word_get0 (o, 1)); } free (o); return i; }
SDB_API int sdb_json_set (Sdb *s, const char *k, const char *p, const char *v, ut32 cas) { const char *beg[3]; const char *end[3]; int l, idx, len[3]; char *str = NULL; Rangstr rs; ut32 c; char *js = sdb_get (s, k, &c); if (!js) return 0; if (cas && c != cas) { free (js); return 0; } rs = json_get (js, p); if (!rs.p) { free (js); return 0; } #define WLEN(x) (int)(size_t)(end[x]-beg[x]) beg[0] = js; end[0] = rs.p + rs.f; len[0] = WLEN (0); beg[1] = v; end[1] = v + strlen (v); len[1] = WLEN (1); beg[2] = rs.p + rs.t; end[2] = js + strlen (js); len[2] = WLEN (2); // TODO: accelerate with small buffer in stack for small jsons str = malloc (len[0]+len[1]+len[2]+1); idx = len[0]; memcpy (str, beg[0], idx); l = len[1]; memcpy (str+idx, beg[1], l); idx += len[1]; l = len[2]; memcpy (str+idx, beg[2], l); str[idx+l] = 0; sdb_set (s, k, str, cas); free (str); free (js); return 1; }
SDB_API char *sdb_array_pop_tail(Sdb *s, const char *key, ut32 *cas) { ut32 kas; char *end, *str = sdb_get (s, key, &kas); if (!str || !*str) { free (str); return NULL; } if (cas && *cas != kas) *cas = kas; for (end = str + strlen (str) - 1; end > str && *end != SDB_RS; end--); if (*end == SDB_RS) *end++ = 0; sdb_set_owned (s, key, str, 0); // XXX: probably wrong return strdup (end); }
int main() { #define DBFILE "___syncget.db" const char *v; Sdb *s = sdb_new0(); unlink (DBFILE); sdb_set (s, "foo", "bar", 0); eprintf ("-> %s\n", sdb_get (s, "foo", NULL)); sdb_file (s, DBFILE); sdb_sync (s); v = sdb_const_get (s, "foo", NULL); if (v && !strcmp ("bar", v)) { eprintf ("OK syncget\n"); return 0; } eprintf ("ERROR syncget: Keys not accessible after sync\n"); return 1; }
// TODO: use proper dwarf api here.. or deprecate static int get_line(RBinFile *arch, ut64 addr, char *file, int len, int *line) { char *ret, *p, *offset_ptr, offset[64]; if (arch->sdb_addrinfo) { offset_ptr = sdb_itoa (addr, offset, 16); ret = sdb_get (arch->sdb_addrinfo, offset_ptr, 0); if (!ret) return R_FALSE; p = strchr (ret, '|'); if (p) { *p = '\0'; strncpy(file, ret, len); *line = atoi(p + 1); return R_TRUE; } } return R_FALSE; }
R_API int r_anal_xrefs_from (RAnal *anal, RList *list, const char *kind, const char *type, ut64 addr) { char *s, *str, *ptr, key[256]; RAnalRef *ref = NULL; int hasnext = 1; snprintf (key, sizeof (key), "%s.%s.0x%"PFMT64x, kind, type, addr); str = sdb_get (DB, key, 0); if (!str) return R_FALSE; for (ptr=str; hasnext; ptr = (char *)sdb_anext (s)) { s = sdb_astring (ptr, &hasnext); if (!(ref = r_anal_ref_new ())) return R_FALSE; ref->addr = addr; ref->at = r_num_get (NULL, s); ref->type = (!strcmp (type, "code"))?'C':'d'; // XXX r_list_append (list, ref); } free (str); return R_TRUE; }
SDB_API char *sdb_array_pop_head(Sdb *s, const char *key, ut32 *cas) { // remove last element in ut32 kas; char *end, *str = sdb_get (s, key, &kas); if (!str || !*str) { free (str); return NULL; } if (cas && *cas != kas) *cas = kas; end = strchr (str, SDB_RS); if (end) { *end = 0; sdb_set (s, key, end + 1, 0); } else { sdb_unset (s, key, 0); } return str; }
static ut64 getFunctionSize(Sdb *db) { ut64 min = UT64_MAX, max = 0; char *c, *bbs = sdb_get (db, "bbs", NULL); bool first = true; sdb_aforeach (c, bbs) { ut64 addr = sdb_atoi (c); ut64 addr_end = sdb_num_get (db, Fbb (addr), NULL); if (first) { min = addr; max = addr_end; first = false; } else { if (addr < min) { min = addr; } if (addr_end > max) { max = addr_end; } } sdb_aforeach_next (c); }
R_API int r_meta_del(RAnal *a, int type, ut64 addr, ut64 size, const char *str) { char key[100], key2[100], *dtr, *s, *p, *next; const char *ptr; int i; if (size == UT64_MAX) { // FULL CLEANUP // XXX: this thing ignores the type if (type == R_META_TYPE_ANY) { sdb_reset (DB); } else { snprintf (key, sizeof (key)-1, "meta.%c", type); dtr = sdb_get (DB, key, 0); for (p = dtr; p; p = next) { s = sdb_anext (p, &next); snprintf (key, sizeof (key)-1, "meta.%c.0x%"PFMT64x, type, sdb_atoi (s)); eprintf ("--> %s\n", key); sdb_unset (DB, key, 0); if (!next) break; } free (dtr); } return R_FALSE; } meta_inrange_del (a, addr, size); snprintf (key, sizeof (key)-1, type==R_META_TYPE_COMMENT ? "meta.C.0x%"PFMT64x : "meta.0x%"PFMT64x, addr); ptr = sdb_const_get (DB, key, 0); if (ptr) { for (i=0; ptr[i]; i++) { if (ptr[i] != SDB_RS) { snprintf (key2, sizeof (key2)-1, "meta.%c.0x%"PFMT64x, ptr[i], addr); sdb_unset (DB, key2, 0); } } } sdb_unset (DB, key, 0); return R_FALSE; }
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; }
R_API int r_anal_fcn_labels (RAnal *anal, RAnalFunction *fcn, int rad) { if (!anal || !fcn) return 0; if (fcn) { char *cur, *token; char *str = sdb_get (DB, LABELS, 0); sdb_aforeach (cur, str) { struct { ut64 addr; char *name; } loc; token = strchr (cur, '/'); if (!token) break; *token = ','; sdb_fmt_tobin (cur, "qz", &loc); switch (rad) { case '*': case 1: anal->printf ("f.%s@0x%08"PFMT64x"\n", loc.name, loc.addr); break; case 'j': eprintf ("TODO\n"); break; default: anal->printf ("0x%08"PFMT64x" %s [%s + %"PFMT64d"]\n", loc.addr, loc.name, fcn->name, loc.addr - fcn->addr, loc.addr); } *token = '/'; sdb_fmt_free (&loc, "qz"); sdb_aforeach_next (cur); } free (str); } else {
static ut64 getFunctionSize(Sdb *db) { #if 1 ut64 min = sdb_num_get (db, Fmin (addr), NULL); ut64 max = sdb_num_get (db, Fmax (addr), NULL); #else ut64 min, max; char *c, *bbs = sdb_get (db, "bbs", NULL); int first = 1; sdb_aforeach (c, bbs) { ut64 addr = sdb_atoi (c); ut64 addr_end = sdb_num_get (db, Fbb(addr), NULL); if (first) { min = addr; max = addr_end; first = 0; } else { if (addr<min) min = addr; if (addr_end>max) max = addr_end; } sdb_aforeach_next (c); }
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_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); } }