// TODO: Add APIs to resize meta? nope, just del and add R_API int r_meta_set_string(RAnal *a, int type, ut64 addr, const char *s) { char key[100], val[2048], *e_str; int ret; ut64 size; int space_idx = a->meta_spaces.space_idx; meta_type_add (a, type, addr); snprintf (key, sizeof (key)-1, "meta.%c.0x%"PFMT64x, type, addr); size = sdb_array_get_num (DB, key, 0, 0); if (!size) { size = strlen (s); meta_inrange_add (a, addr, size); ret = true; } else { ret = false; } if (a->log) { char *msg = r_str_newf (":C%c %s @ 0x%"PFMT64x, type, s, addr); a->log (a, msg); free (msg); } e_str = sdb_encode ((const void*)s, -1); snprintf (val, sizeof (val)-1, "%d,%d,%s", (int)size, space_idx, e_str); sdb_set (DB, key, val, 0); free ((void*)e_str); return ret; }
static void setHint (RAnal *a, const char *type, ut64 addr, const char *s, ut64 ptr) { int idx; char key[128], val[128], *nval = NULL; setf (key, "hint.0x%"PFMT64x, addr); idx = sdb_array_indexof (DB, key, type, 0); if (s) nval = sdb_encode ((const ut8*)s, -1); else nval = sdb_itoa (ptr, val, 16); if (idx != -1) { if (!s) nval = sdb_itoa (ptr, val, 16); sdb_array_set (DB, key, idx+1, nval, 0); } else { sdb_array_push (DB, key, nval, 0); sdb_array_push (DB, key, type, 0); } if (s) free (nval); }
static int base64encode() { char *out; int len = 0; ut8 *in = (ut8*)stdin_slurp (&len); if (!in) { return 0; } out = sdb_encode (in, len); if (!out) { free (in); return 1; } puts (out); free (out); free (in); return 0; }
// TODO: Add APIs to resize meta? nope, just del and add R_API int r_meta_set_string(RAnal *a, int type, ut64 addr, const char *s) { char key[100], val[2048], *e_str; int ret; ut64 size; snprintf (key, sizeof (key)-1, "meta.%c", type); sdb_array_add_num (DB, key, addr, 0); snprintf (key, sizeof (key)-1, "meta.%c.0x%"PFMT64x, type, addr); size = sdb_array_get_num (DB, key, 0, 0); if (!size) { size = strlen (s); meta_inrange_add (a, addr, size); ret = R_TRUE; } else ret = R_FALSE; e_str = sdb_encode ((const void*)s, -1); snprintf (val, sizeof (val)-1, "%d,%s", (int)size, e_str); sdb_set (DB, key, val, 0); free ((void*)e_str); 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; }
SDB_API char *sdb_fmt_tostr(void *p, const char *fmt) { char buf[128], *e_str, *out = NULL; int n, len = 0; for (; *fmt; fmt++) { n = 4; switch (*fmt) { case 'b': concat (sdb_itoa ((ut64)*((ut8*)(p+len)), buf, 10)); break; case 'h': concat (sdb_itoa ((ut64)*((short*)(p+len)), buf, 10)); break; case 'd': concat (sdb_itoa ((ut64)*((int*)(p+len)), buf, 10)); break; case 'q': concat (sdb_itoa (*((ut64*)(p+len)), buf, 10)); n = 8; break; case 'z': concat (p+len); break; case 's': e_str = sdb_encode ((const ut8*)*((char**)(p+len)), -1); concat (e_str); free (e_str); break; case 'p': concat (sdb_itoa ((ut64)*((size_t*)(p+len)), buf, 16)); n = sizeof (size_t); break; } len += R_MAX ((long)sizeof (void*), n); // align } return out; }
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; }
void r_comment_vars(RCore *core, const char *input) { //TODO enable base64 and make it the default for C* RAnalFunction *fcn = r_anal_get_fcn_in (core->anal, core->offset, 0); int idx; char *oname = NULL, *name = NULL; char *oldcomment = NULL; char *heap_comment = NULL; RAnalVar *var; if (input[1] == '?' || (input[0] != 'b' && input[0] != 'r' && input[0] != 's') ) { r_comment_var_help (core, input[0]); return; } if (!fcn) { eprintf ("Cant find function here\n"); return; } oname = name = strdup (input + 2); while (*name == ' ') { name++; } switch (input[1]) { case '*': case '\0': { RList *var_list; RListIter *iter; var_list = r_anal_var_list (core->anal, fcn, input[0]); r_list_foreach (var_list, iter, var) { oldcomment = r_meta_get_var_comment (core->anal, input[0], var->delta, fcn->addr); if (!oldcomment) { continue; } if (!input[1]) { r_cons_printf ("%s : %s\n", var->name, oldcomment); } else { r_cons_printf ("\"Cv%c %s base64:%s @ 0x%08"PFMT64x"\"\n", input[0], var->name, sdb_encode ((const ut8 *) oldcomment, strlen(oldcomment)), fcn->addr); } } } break; case ' ': { // TODO check that idx exist char *comment = strstr (name, " "); if (comment) { // new comment given if (*comment) { *comment++ = 0; } if (!strncmp (comment, "base64:", 7)) { heap_comment = (char *)sdb_decode (comment + 7, NULL); comment = heap_comment; } } var = r_anal_var_get_byname (core->anal, fcn, name); if (var) { idx = var->delta; } else if (!strncmp (name, "0x", 2)) { idx = (int) r_num_get (NULL, name); } else if (!strncmp (name, "-0x", 3)) { idx = -(int) r_num_get (NULL, name+1); } else { eprintf ("cant find variable named `%s`\n",name); free (heap_comment); break; } r_anal_var_free (var); if (!r_anal_var_get (core->anal, fcn->addr, input[0], 1, idx)) { eprintf ("cant find variable at given offset\n"); } else { oldcomment = r_meta_get_var_comment (core->anal, input[0], idx, fcn->addr); if (oldcomment) { if (comment && *comment) { char *text = r_str_newf ("%s\n%s", oldcomment, comment); r_meta_set_var_comment (core->anal, input[0], idx, fcn->addr, text); free (text); } else { r_cons_println (oldcomment); } } else { r_meta_set_var_comment (core->anal, input[0], idx, fcn->addr, comment); } } free (heap_comment); } break; case '-': var = r_anal_var_get_byname (core->anal,fcn, name); if (var) { idx = var->delta; } else if (!strncmp (name, "0x", 2)) { idx = (int) r_num_get (NULL, name); } else if (!strncmp (name, "-0x", 3)) { idx = -(int) r_num_get (NULL, name+1); }else { eprintf ("cant find variable named `%s`\n",name); break; } r_anal_var_free (var); //XXX TODO here we leak a var if (!r_anal_var_get (core->anal, fcn->addr, input[0],1,idx)) { eprintf ("cant find variable at given offset\n"); break; } r_meta_var_comment_del (core->anal, input[0], idx, fcn->addr); break; case '!': { char *comment; var = r_anal_var_get_byname (core->anal,fcn, name); if (!var) { eprintf ("cant find variable named `%s`\n",name); break; } oldcomment = r_meta_get_var_comment (core->anal, input[0], var->delta, fcn->addr); comment = r_core_editor (core, NULL, oldcomment); if (comment) { r_meta_var_comment_del (core->anal, input[0], var->delta, fcn->addr); r_meta_set_var_comment (core->anal, input[0], var->delta, fcn->addr, comment); free (comment); } r_anal_var_free (var); } break; }
static void printmetaitem(RAnal *a, RAnalMetaItem *d, int rad) { char *pstr, *str; //eprintf ("%d %d\n", d->space, a->meta_spaces.space_idx); if (a->meta_spaces.space_idx != -1) { if (a->meta_spaces.space_idx != d->space) { return; } } str = r_str_escape (d->str); if (str || d->type == 'd') { if (d->type=='s' && !*str) { free (str); return; } if (!str) { pstr = ""; } else if (d->type != 'C') { r_name_filter (str, 0); pstr = str; } else pstr = d->str; // r_str_sanitize (str); switch (rad) { case 'j': a->cb_printf ("{\"offset\":%"PFMT64d", \"type\":\"%s\", \"name\":\"%s\"}", d->from, r_meta_type_to_string (d->type), str); break; case 0: case 1: case '*': default: switch (d->type) { case 'C': { const char *type = r_meta_type_to_string (d->type); char *s = sdb_encode ((const ut8*)pstr, -1); if (!s) s = strdup (pstr); if (rad) { if (!strcmp (type, "CCu")) { a->cb_printf ("%s base64:%s @ 0x%08"PFMT64x"\n", type, s, d->from); } else { a->cb_printf ("%s %s @ 0x%08"PFMT64x"\n", type, pstr, d->from); } } else { if (!strcmp (type, "CCu")) { char *mys = r_str_escape (pstr); a->cb_printf ("0x%08"PFMT64x" %s \"%s\"\n", d->from, type, mys); free (mys); } else { a->cb_printf ("0x%08"PFMT64x" %s \"%s\"\n", d->from, type, pstr); } } free (s); } break; case 'h': /* hidden */ case 's': /* string */ if (rad) { a->cb_printf ("%s %d @ 0x%08"PFMT64x" # %s\n", r_meta_type_to_string (d->type), (int)d->size, d->from, pstr); } else { // TODO: use b64 here a->cb_printf ("0x%08"PFMT64x" string[%d] \"%s\"\n", d->from, (int)d->size, pstr); } break; case 'd': /* data */ if (rad) { a->cb_printf ("%s %d @ 0x%08"PFMT64x"\n", r_meta_type_to_string (d->type), (int)d->size, d->from); } else { a->cb_printf ("0x%08"PFMT64x" data %s %d\n", d->from, r_meta_type_to_string (d->type), (int)d->size); } break; case 'm': /* magic */ case 'f': /* formatted */ if (rad) { a->cb_printf ("%s %d %s @ 0x%08"PFMT64x"\n", r_meta_type_to_string (d->type), (int)d->size, pstr, d->from); } else { const char *dtype = d->type=='m'?"magic":"format"; a->cb_printf ("0x%08"PFMT64x" %s %d %s\n", d->from, dtype, (int)d->size, pstr); } break; default: if (rad) { a->cb_printf ("%s %d 0x%08"PFMT64x" # %s\n", r_meta_type_to_string (d->type), (int)d->size, d->from, pstr); } else { // TODO: use b64 here a->cb_printf ("0x%08"PFMT64x" array[%d] %s %s\n", d->from, (int)d->size, r_meta_type_to_string (d->type), pstr); } break; } break; } if (str) free (str); } }