R_API int r_anal_var_add (RAnal *a, ut64 addr, int scope, int delta, char kind, const char *type, int size, const char *name) { char *var_def; if (!kind) kind ='v'; if (!type) type = "int"; //eprintf ("VAR ADD 0x%llx - %d\n", addr, delta); switch (kind) { case 'a': case 'r': case 'v': break; default: eprintf ("Invalid var kind '%c'\n", kind); return false; } var_def = sdb_fmt (0,"%c,%s,%d,%s", kind, type, size, name); if (scope>0) { /* local variable */ char *fcn_key = sdb_fmt (1, "fcn.0x%"PFMT64x".%c", addr, kind); char *var_key = sdb_fmt (2, "var.0x%"PFMT64x".%c.%d.%d", addr, kind, scope, delta); char *name_key = sdb_fmt (3, "var.0x%"PFMT64x".%c.%d.%s", addr, kind, scope, name); char *shortvar = sdb_fmt (4, "%d.%d", scope, delta); sdb_array_add (DB, fcn_key, shortvar, 0); sdb_set (DB, var_key, var_def, 0); sdb_num_set (DB, name_key, delta, 0); } else { /* global variable */ char *var_global = sdb_fmt (1, "var.0x%"PFMT64x, addr); char *var_def = sdb_fmt (2,"%c.%s,%d,%s", kind, type, size, name); sdb_array_add (DB, var_global, var_def, 0); } // ls_sort (DB->ht->list, mystrcmp); return true; }
R_API int r_anal_var_add (RAnal *a, ut64 addr, int scope, int delta, char kind, const char *type, int size, const char *name) { char key[128], key2[128], val[128]; switch (kind) { case 'a': case 'r': case 'v': break; default: eprintf ("Invalid var kind\n"); return R_FALSE; } if (scope>0) { // local SETKEY("fcn.0x%"PFMT64x".%c", addr, kind); SETVAL("var.0x%"PFMT64x".%c.%d.%d", addr, kind, scope, delta); sdb_array_add (DB, key, val, 0); strcpy (key, val); SETVAL("%s,%d,%s", type, size, name); sdb_set (DB, key, val, 0); #if 0 fcn.0x80480.a=1.8,1.16 fcn.0x80480.a.1.8=type,size,name fcn.0x80480.a.1.16=type,size,name #endif SETKEY("var.0x%"PFMT64x".%d.%d", addr, scope, delta); // TODO: link to function // fcn.<addr>.kind+=var.0x%"PFMT64x".. } else { // global snprintf (key, "var.0x%"PFMT64x, addr); } sdb_array_add (DB, key, val, 0); return R_TRUE; }
static int trace_hook_reg_read(RAnalEsil *esil, const char *name, ut64 *res, int *size) { int ret = 0; if (*name=='0') { //eprintf ("Register not found in profile\n"); return 0; } if (ocbs.hook_reg_read) { RAnalEsilCallbacks cbs = esil->cb; esil->cb = ocbs; ret = ocbs.hook_reg_read (esil, name, res, size); esil->cb = cbs; } if (!ret && esil->cb.reg_read) { ret = esil->cb.reg_read (esil, name, res, size); } if (ret) { ut64 val = *res; //eprintf ("[ESIL] REG READ %s 0x%08"PFMT64x"\n", name, val); sdb_array_add (DB, KEY ("reg.read"), name, 0); sdb_num_set (DB, KEYREG ("reg.read", name), val, 0); } //else { //eprintf ("[ESIL] REG READ %s FAILED\n", name); //} return ret; }
R_API int r_anal_var_add(RAnal *a, ut64 addr, int scope, int delta, char kind, const char *type, int size, const char *name) { char *var_def; if (!kind) { kind = R_ANAL_VAR_KIND_BPV; } if (!type) { type = "int"; } switch (kind) { case R_ANAL_VAR_KIND_BPV: // base pointer var/args case R_ANAL_VAR_KIND_SPV: // stack pointer var/args case R_ANAL_VAR_KIND_REG: // registers args break; default: eprintf ("Invalid var kind '%c'\n", kind); return false; } var_def = sdb_fmt (0,"%c,%s,%d,%s", kind, type, size, name); if (scope > 0) { char *sign = ""; if (delta < 0) { delta = -delta; sign = "_"; } /* local variable */ char *fcn_key = sdb_fmt (1, "fcn.0x%"PFMT64x".%c", addr, kind); char *var_key = sdb_fmt (2, "var.0x%"PFMT64x".%c.%d.%s%d", addr, kind, scope, sign, delta); char *name_key = sdb_fmt (3, "var.0x%"PFMT64x".%d.%s", addr, scope, name); char *shortvar = sdb_fmt (4, "%d.%s%d", scope, sign, delta); sdb_array_add (DB, fcn_key, shortvar, 0); sdb_set (DB, var_key, var_def, 0); if (*sign) { delta = -delta; } char *name_val = sdb_fmt (5, "%c,%d", kind, delta); sdb_set (DB, name_key, name_val, 0); } else { /* global variable */ char *var_global = sdb_fmt (1, "var.0x%"PFMT64x, addr); char *var_def = sdb_fmt (2,"%c.%s,%d,%s", kind, type, size, name); sdb_array_add (DB, var_global, var_def, 0); } // ls_sort (DB->ht->list, mystrcmp); return true; }
SDB_API int sdb_array_add_num(Sdb *s, const char *key, ut64 val, ut32 cas) { char valstr10[64], valstr16[64]; char *v10 = sdb_itoa (val, valstr10, 10); char *v16 = sdb_itoa (val, valstr16, 16); // TODO: optimize // TODO: check cas vs mycas if (sdb_array_contains (s, key, v10, NULL)) return 0; return sdb_array_add (s, key, v16, cas); // TODO: v10 or v16 }
bool test_sdb_array_add_remove(void) { Sdb *db = sdb_new (NULL, NULL, false); sdb_array_add (db, "foo", "foo", 0); sdb_array_add (db, "foo", "bar", 0); sdb_array_add (db, "foo", "cow", 0); mu_assert_streq (sdb_const_get (db, "foo", 0), "foo,bar,cow", "Not all items found"); sdb_array_remove (db, "foo", "bar", 0); mu_assert_streq (sdb_const_get (db, "foo", 0), "foo,cow", "bar was not deleted"); sdb_array_remove (db, "foo", "nothing", 0); mu_assert_streq (sdb_const_get (db, "foo", 0), "foo,cow", "nothing should be deleted"); sdb_array_remove (db, "foo", "cow", 0); sdb_array_remove (db, "foo", "foo", 0); mu_assert_eq ((int)(size_t)sdb_const_get (db, "foo", 0), (int)(size_t)NULL, "all elements should be deleted"); sdb_free (db); mu_end; }
R_API int r_anal_fcn_label_set (RAnal *anal, RAnalFunction *fcn, const char *name, ut64 addr) { if (!anal || !fcn) return R_FALSE; if (sdb_add (DB, ADDR(addr), name, 0)) { if (sdb_num_add (DB, LABEL(name), addr, 0)) { sdb_array_add (DB, LABELS, ADDRLABEL (addr, name), 0); return R_TRUE; } else { sdb_unset (DB, ADDR(addr), 0); } } return R_FALSE; }
static int trace_hook_reg_write(RAnalEsil *esil, const char *name, ut64 val) { int ret = 0; eprintf ("[ESIL] REG WRITE %s 0x%08"PFMT64x"\n", name, val); sdb_array_add (DB, KEY ("reg.write"), name, 0); sdb_num_set (DB, KEYREG ("reg.write", name), val, 0); if (ocbs.hook_reg_write) { RAnalEsilCallbacks cbs = esil->cb; esil->cb = ocbs; ret = ocbs.hook_reg_write (esil, name, val); esil->cb = cbs; } return ret; }
static int trace_hook_reg_read(RAnalEsil *esil, const char *name, ut64 *res) { int ret = 0; ut64 val = 0LL; if (*name=='0') { eprintf ("Register not found in profile\n"); return 0; } if (esil->cb.reg_read) { (void)esil->cb.reg_read (esil, name, &val); } eprintf ("[ESIL] REG READ %s 0x%08"PFMT64x"\n", name, val); sdb_array_add (DB, KEY ("reg.read"), name, 0); sdb_num_set (DB, KEYREG ("reg.read", name), val, 0); if (ocbs.hook_reg_read) { RAnalEsilCallbacks cbs = esil->cb; esil->cb = ocbs; ret = ocbs.hook_reg_read (esil, name, res); esil->cb = cbs; } return ret; }
static int meta_add(RAnal *a, int type, int subtype, ut64 from, ut64 to, const char *str) { int space_idx = a->meta_spaces.space_idx; char *e_str, key[100], val[2048]; int exists; if (from > to) { return false; } if (from == to) { to = from + 1; } if (type == 100 && (to - from) < 1) { return false; } /* set entry */ e_str = sdb_encode ((const void*)str, -1); RAnalMetaItem mi = {from, to, (int)(to - from), type, subtype, e_str, space_idx}; meta_serialize (&mi, key, sizeof (key), val, sizeof (val)); exists = sdb_exists (DB, key); sdb_set (DB, key, val, 0); free (e_str); // XXX: This is totally inefficient, using array_add withuot // checking return value is wrong practice, also it may lead // to inconsistent DB, and pretty bad performance. We should // store this list in a different storage that doesnt have // those limits and it's O(1) instead of O(n) snprintf (key, sizeof (key) - 1, "meta.0x%"PFMT64x, from); if (exists) { const char *value = sdb_const_get (DB, key, 0); int idx = sdb_array_indexof (DB, key, value, 0); sdb_array_delete (DB, key, idx, 0); } snprintf (val, sizeof (val)-1, "%c", type); sdb_array_add (DB, key, val, 0); meta_inrange_add (a, from, to - from); return true; }
R_API int r_meta_add(RAnal *a, int type, ut64 from, ut64 to, const char *str) { int exists; char *e_str, key[100], val[2048]; if (from>to) return R_FALSE; if (from == to) to = from+1; if (type == 100) { if ((to-from)<3) { return R_FALSE; } } /* set entry */ e_str = sdb_encode ((const void*)str, -1); snprintf (key, sizeof (key)-1, "meta.%c.0x%"PFMT64x, type, from); snprintf (val, sizeof (val)-1, "%d,%s", (int)(to-from), e_str); exists = sdb_exists (DB, key); sdb_set (DB, key, val, 0); free (e_str); // XXX: This is totally inefficient, using array_add withuot // checking return value is wrong practice, also it may lead // to inconsistent DB, and pretty bad performance. We should // store this list in a different storage that doesnt have // those limits and it's O(1) instead of O(n) if (!exists) { /* set type index */ snprintf (key, sizeof (key)-1, "meta.0x%"PFMT64x, from); snprintf (val, sizeof (val)-1, "%c", type); sdb_array_add (DB, key, val, 0); /* set type index */ snprintf (key, sizeof (key)-1, "meta.%c", type); sdb_array_add_num (DB, key, from, 0); } return R_TRUE; }
static int hook_command(RAnalEsil *esil, const char *op) { sdb_array_add (esil->stats, "ops.list", op, 0); return 0; }
static int hook_flag_read(RAnalEsil *esil, const char *flag, ut64 *num) { sdb_array_add (esil->stats, "flg.read", flag, 0); return 0; }
static int hook_reg_write(RAnalEsil *esil, const char *name, ut64 val) { sdb_array_add (esil->stats, "reg.write", name, 0); return 0; }
static int hook_reg_read(RAnalEsil *esil, const char *name, ut64 *res, int *size) { const char *key = (*name>='0' && *name<='9')? "num.load": "reg.read"; sdb_array_add (esil->stats, key, name, 0); return 0; }
static int hook_reg_read(RAnalEsil *esil, const char *name, ut64 *res) { if (*name>='0' && *name<='9') sdb_array_add (esil->stats, "num.load", name, 0); else sdb_array_add (esil->stats, "reg.read", name, 0); return 0; }