R_API int r_meta_list_cb(RAnal *a, int type, int rad, SdbForeachCallback cb, void *user) { RAnalMetaUserItem ui = { a, type, rad, cb, user, 0 }; if (rad=='j') a->cb_printf ("["); if (cb) { sdb_foreach (DB, cb, &ui); } else { sdb_foreach (DB, meta_print_item, &ui); } if (rad=='j') a->cb_printf ("]\n"); return ui.count; }
R_API void r_anal_xrefs_list(RAnal *anal, int rad) { switch (rad) { case 1: case '*': sdb_foreach (DB, xrefs_list_cb_rad, anal); break; case 'j': anal->printf ("{"); sdb_foreach (DB, xrefs_list_cb_json, anal); anal->printf ("}\n"); break; default: sdb_foreach (DB, xrefs_list_cb_plain, anal); break; } }
R_API int r_meta_list_cb(RAnal *a, int type, int rad, SdbForeachCallback cb, void *user, ut64 addr) { RAnalFunction *fcn = (addr != UT64_MAX) ? r_anal_get_fcn_at (a, addr, 0) : NULL; RAnalMetaUserItem ui = { a, type, rad, cb, user, 0, fcn}; if (rad == 'j') { a->cb_printf ("["); } if (cb) { sdb_foreach (DB, cb, &ui); } else { sdb_foreach (DB, meta_print_item, &ui); } if (rad == 'j') { a->cb_printf ("]\n"); } return ui.count; }
R_API void r_debug_signal_list(RDebug *dbg, int mode) { dbg->_mode = mode; switch (mode) { case 0: case 1: sdb_foreach (DB, siglistcb, dbg); break; case 2: r_cons_strcat ("["); sdb_foreach (DB, siglistjsoncb, dbg); r_cons_strcat ("]"); r_cons_newline(); break; } dbg->_mode = 0; }
// TODO: Deprecate R_API int r_meta_list(RAnal *a, int type, int rad) { RAnalMetaUserItem ui = { a, type, rad }; if (rad=='j') a->printf ("["); sdb_foreach (DB, meta_print_item, &ui); if (rad=='j') a->printf ("]\n"); return 0; }
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; }
R_API RList *r_syscall_list(RSyscall *s) { RList *list; if (!s || !s->db) { return NULL; } // show list of syscalls to stdout list = r_list_newf ((RListFree)r_syscall_item_free); sdb_foreach (s->db, callback_list, list); return list; }
R_API RDebug *r_debug_free(RDebug *dbg) { if (!dbg) return NULL; // TODO: free it correctly.. we must ensure this is an instance and not a reference.. r_bp_free (dbg->bp); //r_reg_free(&dbg->reg); r_list_free (dbg->snaps); sdb_free (dbg->sgnls); r_tree_free (dbg->tree); sdb_foreach (dbg->tracenodes, (SdbForeachCallback)free_tracenodes_entry, dbg); sdb_free (dbg->tracenodes); //r_debug_plugin_free(); r_debug_trace_free (dbg); free (dbg); return NULL; }
R_API void r_anal_xrefs_list(RAnal *anal, int rad) { switch (rad) { case 1: case '*': sdb_foreach (DB, (SdbForeachCallback)xrefs_list_cb_rad, anal); break; case 'j': { anal->cb_printf ("{"); bool is_first = true; SdbListIter *sdb_iter; SdbKv *kv; SdbList *sdb_list = sdb_foreach_match (DB, "^ref.", false); ls_foreach (sdb_list, sdb_iter, kv) { is_first = xrefs_list_cb_json (anal, is_first, kv->key, kv->value); } ls_free (sdb_list); anal->cb_printf ("}\n"); } break; default: sdb_foreach (DB, (SdbForeachCallback)xrefs_list_cb_plain, anal); break; }
R_API RList *r_syscall_list(RSyscall *s) { if (!s || !s->db) return NULL; sdb_foreach (s->db, callback_list, s); // XXX: this method must be deprecated.. we have to use sdb to access this info return NULL; #if 0 RListIter *iter; RPairItem *o; RList *list = r_pair_list (s->db, NULL); RList *olist = r_list_new (); olist->free = (RListFree)r_syscall_item_free; r_list_foreach (list, iter, o) { RSyscallItem *si = r_syscall_item_new_from_string (o->k, o->v); if (!strchr (si->name, '.')) r_list_append (olist, si); }
R_API bool r_sign_delete(RAnal *a, const char *name) { struct ctxDeleteCB ctx; char k[R_SIGN_KEY_MAXSZ]; // Remove all zigns if (name[0] == '*') { if (a->zign_spaces.space_idx == -1) { sdb_reset (a->sdb_zigns); return true; } else { ctx.anal = a; serializeKey (a, a->zign_spaces.space_idx, "", ctx.buf); sdb_foreach (a->sdb_zigns, deleteBySpaceCB, &ctx); return true; } } // Remove specific zign serializeKey (a, a->zign_spaces.space_idx, name, k); return sdb_remove (a->sdb_zigns, k, 0); }
R_API void r_anal_pin_list(RAnal *a) { sdb_foreach (DB, cb_list, a); }
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; }
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; }
R_API void r_debug_tracenodes_reset (RDebug *dbg) { sdb_foreach (dbg->tracenodes, (SdbForeachCallback)free_tracenodes_entry, dbg); sdb_reset (dbg->tracenodes); }
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 'u': // "tu" switch (input[1]) { case '?': { const char *help_message[] = { "USAGE tu[...]", "", "", "tu", "", "List all loaded unions", "tu?", "", "show this help", NULL }; r_core_cmd_help (core, help_message); } break; case 0: sdb_foreach (core->anal->sdb_types, stdprintifunion, core); break; } break; case 'k': // "tk" if (input[1] == ' ') { sdb_query (core->anal->sdb_types, input + 2); } else sdb_query (core->anal->sdb_types, "*"); fflush (stdout); break; case 's': // "ts" switch (input[1]) { case '?': { const char *help_message[] = { "USAGE ts[...]", "", "", "ts", "", "List all loaded structs", "ts?", "", "show this help", NULL }; r_core_cmd_help (core, help_message); } break; case 0: sdb_foreach (core->anal->sdb_types, stdprintifstruct, core); break; } break; case 'b': { char *p, *s = (strlen (input) > 1)? strdup (input + 2): NULL; const char *isenum; p = s? strchr (s, ' '): NULL; if (p) { *p++ = 0; // dupp in core.c (see getbitfield()) isenum = sdb_const_get (core->anal->sdb_types, s, 0); if (isenum && !strcmp (isenum, "enum")) { *--p = '.'; const char *res = sdb_const_get (core->anal->sdb_types, s, 0); if (res) r_cons_println (res); else eprintf ("Invalid enum member\n"); } else { eprintf ("This is not an enum\n"); } } else { eprintf ("Missing value\n"); } free (s); } break; case 'e': { if (!input[1]) { char *name = NULL; SdbKv *kv; SdbListIter *iter; SdbList *l = sdb_foreach_list (core->anal->sdb_types); ls_foreach (l, iter, kv) { if (!strcmp (kv->value, "enum")) { if (!name || strcmp (kv->value, name)) { free (name); name = strdup (kv->key); r_cons_println (name); } } } free (name); ls_free (l); break; } if (input[1] == '?') { const char *help_message[] = { "USAGE te[...]", "", "", "te", "", "List all loaded enums", "te", " <enum> <value>", "Show name for given enum number", "te?", "", "show this help", NULL }; r_core_cmd_help (core, help_message); break; } char *p, *s = strdup (input + 2); const char *isenum; p = strchr (s, ' '); if (p) { *p++ = 0; isenum = sdb_const_get (core->anal->sdb_types, s, 0); if (isenum && !strncmp (isenum, "enum", 4)) { const char *q = sdb_fmt (0, "%s.0x%x", s, (ut32)r_num_math (core->num, p)); const char *res = sdb_const_get (core->anal->sdb_types, q, 0); if (res) r_cons_println (res); } else { eprintf ("This is not an enum\n"); } } else { //eprintf ("Missing value\n"); r_core_cmdf (core, "t~&%s,=0x", s); } free (s); } break; case ' ': { const char *isenum = sdb_const_get (core->anal->sdb_types, input + 1, 0); if (isenum && !strcmp (isenum, "enum")) { eprintf ("IS ENUM! \n"); } else { char *fmt = r_anal_type_format (core->anal, input + 1); if (fmt) { r_str_chop (fmt); r_cons_printf ("pf %s\n", fmt); free (fmt); } else eprintf ("Cannot find '%s' type\n", input + 1); } } break; // t* - list all types in 'pf' syntax case '*': sdb_foreach (core->anal->sdb_types, typelist, core); break; case 0: sdb_foreach (core->anal->sdb_types, sdbforcb, core); break; case 'o': if (!r_sandbox_enable (0)) { if (input[1] == ' ') { const char *filename = input + 2; char *homefile = NULL; if (*filename == '~') { if (filename[1] && filename[2]) { homefile = r_str_home (filename + 2); filename = homefile; } } if (!strcmp (filename, "-")) { char *out, *tmp; tmp = r_core_editor (core, NULL, ""); if (tmp) { out = r_parse_c_string (tmp); if (out) { // r_cons_strcat (out); save_parsed_type (core, out); free (out); } free (tmp); } } else { char *out = r_parse_c_file (filename); if (out) { //r_cons_strcat (out); save_parsed_type (core, out); free (out); } //r_anal_type_loadfile (core->anal, filename); } free (homefile); } else if (input[1] == 's') { const char *dbpath = input + 3; if (r_file_exists (dbpath)) { Sdb *db_tmp = sdb_new (0, dbpath, 0); sdb_merge (core->anal->sdb_types, db_tmp); sdb_close (db_tmp); sdb_free (db_tmp); } } } else { eprintf ("Sandbox: system call disabled\n"); } 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); r_cons_printf ("Note: The td command should be put between double quotes\n" "Example: \" td struct foo {int bar;int cow};\"" "\nt"); } else if (input[1] == ' ') { char tmp[8192]; snprintf (tmp, sizeof (tmp) - 1, "%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); save_parsed_type (core, out); free (out); } } else { eprintf ("Invalid use of td. See td? for help\n"); } break; // tl - link a type to an address case 'l': switch (input[1]) { case '?': { const char *help_message[] = { "Usage:", "", "", "tl", "", "list all links in readable format", "tl", "[typename]", "link a type to current adress.", "tl", "[typename] = [address]", "link type to given address.", "tls", "[address]", "show link at given address", "tl-*", "", "delete all links.", "tl-", "[address]", "delete link at given address.", "tl*", "", "list all links in radare2 command format", "tl?", "", "print this help.", NULL }; r_core_cmd_help (core, help_message); } break; case ' ': { char *type = strdup (input + 2); char *ptr = strchr (type, '='); ut64 addr; if (ptr) { *ptr++ = 0; r_str_chop (ptr); if (ptr && *ptr) { addr = r_num_math (core->num, ptr); } else { eprintf ("address is unvalid\n"); free (type); break; } } else { addr = core->offset; } r_str_chop (type); char *tmp = sdb_get (core->anal->sdb_types, type, 0); if (tmp && *tmp) { r_anal_type_link (core->anal, type, addr); free (tmp); } else { eprintf ("unknown type %s\n", type); } free (type); } break; case 's': { int ptr; char *addr = strdup (input + 2); SdbKv *kv; SdbListIter *sdb_iter; SdbList *sdb_list = sdb_foreach_list (core->anal->sdb_types); r_str_chop (addr); ptr = r_num_math (NULL, addr); //r_core_cmdf (core, "tl~0x%08"PFMT64x" = ", addr); ls_foreach (sdb_list, sdb_iter, kv) { char *linkptr; if (strncmp (kv->key, "link.", strlen ("link."))) { continue; } linkptr = sdb_fmt (-1,"0x%s", kv->key + strlen ("link.")); if (ptr == r_num_math (NULL, linkptr)) { linklist_readable (core, kv->key, kv->value); } } free (addr); ls_free (sdb_list); } break; case '-': switch (input[2]) { case '*': sdb_foreach (core->anal->sdb_types, sdbdeletelink, core); break; case ' ': { const char *ptr = input + 3; ut64 addr = r_num_math (core->num, ptr); r_anal_type_unlink (core->anal, addr); } break; } break; case '*': sdb_foreach (core->anal->sdb_types, linklist, core); break; case '\0': sdb_foreach (core->anal->sdb_types, linklist_readable, core); break; }
R_API void r_debug_signal_list(RDebug *dbg, int mode) { dbg->_mode = mode; sdb_foreach (DB, siglistcb, dbg); dbg->_mode = 0; }
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 'k': if (input[1] == ' ') { sdb_query (core->anal->sdb_types, input + 2); } else sdb_query (core->anal->sdb_types, "*"); break; case 's': { char *q, *p, *o, *e; p = o = strdup (input + 1); for (;;) { if (*p == '\0') { eprintf ("Usage: ts <k>=<v> Set fields at curseek linked type\n"); break; } 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 'b': { char *p, *s = (strlen (input) > 1)? strdup (input + 2): NULL; const char *isenum; p = s? strchr (s, ' '): NULL; if (p) { *p++ = 0; // dupp in core.c (see getbitfield()) isenum = sdb_const_get (core->anal->sdb_types, s, 0); if (isenum && !strcmp (isenum, "enum")) { *--p = '.'; const char *res = sdb_const_get (core->anal->sdb_types, s, 0); if (res) r_cons_printf ("%s\n", res); else eprintf ("Invalid enum member\n"); } else { eprintf ("This is not an enum\n"); } } else { eprintf ("Missing value\n"); } free (s); } break; case 'e': { if (!input[1]) { char *name = NULL; SdbKv *kv; SdbListIter *iter; SdbList *l = sdb_foreach_list (core->anal->sdb_types); ls_foreach (l, iter, kv) { if (!strcmp (kv->value, "enum")) { if (!name || strcmp (kv->value, name)) { free (name); name = strdup (kv->key); r_cons_printf ("%s\n", name); } } } free (name); ls_free (l); break; } char *p, *s = strdup (input + 2); const char *isenum; p = strchr (s, ' '); if (p) { *p++ = 0; isenum = sdb_const_get (core->anal->sdb_types, s, 0); if (isenum && !strcmp (isenum, "enum")) { const char *q = sdb_fmt (0, "%s.0x%x", s, (ut32)r_num_math (core->num, p)); const char *res = sdb_const_get (core->anal->sdb_types, q, 0); if (res) r_cons_printf ("%s\n", res); } else { eprintf ("This is not an enum\n"); } } else { //eprintf ("Missing value\n"); r_core_cmdf (core, "t~&%s,=0x", s); } free (s); } break; case ' ': { const char *isenum = sdb_const_get (core->anal->sdb_types, input + 1, 0); if (isenum && !strcmp (isenum, "enum")) { eprintf ("IS ENUM! \n"); } else { 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; // t* - list all types in 'pf' syntax case '*': sdb_foreach (core->anal->sdb_types, typelist, core); break; case 0: sdb_foreach (core->anal->sdb_types, sdbforcb, core); break; case 'o': if (!r_sandbox_enable (0)) { if (input[1] == ' ') { const char *filename = input + 2; char *homefile = NULL; if (*filename == '~') { if (filename[1] && filename[2]) { homefile = r_str_home (filename + 2); filename = homefile; } } if (!strcmp (filename, "-")) { char *out, *tmp; tmp = r_core_editor (core, NULL, ""); 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); } free (homefile); } } else { eprintf ("Sandbox: system call disabled\n"); } 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); r_cons_printf ("Note: The td command should be put between double quotes\n" "Example: \" td struct foo {int bar;int cow};\"" "\nt"); } else if (input[1] == ' ') { char tmp[8192]; snprintf (tmp, sizeof (tmp) - 1, "%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] == '*') { sdb_foreach (core->anal->sdb_types, sdbdelete, core); } else { const char *name = input + 1; while (IS_WHITESPACE (*name)) name++; if (*name) { SdbKv *kv; SdbListIter *iter; int tmp_len = strlen (name); char *tmp = malloc (tmp_len + 2); r_anal_type_del (core->anal, name); if (tmp) { snprintf (tmp, tmp_len + 1, "%s.", name); SdbList *l = sdb_foreach_list (core->anal->sdb_types); ls_foreach (l, iter, kv) { if (!strncmp (kv->key, tmp, tmp_len - 1)) r_anal_type_del (core->anal, kv->key); } free (tmp); } } else eprintf ("Invalid use of t- . See t-? for help.\n"); }
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 'k': if (input[1]==' ') { sdb_query (core->anal->sdb_types, input+2); } else sdb_query (core->anal->sdb_types, "*"); break; case 's': { char *q, *p, *o, *e; p = o = strdup (input+1); for (;;) { if (*p == '\0'){ eprintf ("Usage: ts <k>=<v> Set fields at curseek linked type\n"); break; } 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 'b': { int i; char *p, *s = (strlen (input) > 1) ? strdup (input+2): NULL; const char *isenum; p = s ? strchr (s, ' ') : NULL; if (p) { *p++ = 0; // dupp in core.c (see getbitfield()) #if 1 isenum = sdb_const_get (core->anal->sdb_types, s, 0); if (isenum && !strcmp (isenum, "enum")) { int empty = 1; ut32 num = (ut32)r_num_math (core->num, p); r_cons_printf ("0x%08"PFMT64x" : ", num); for (i=0; i< 32; i++) { if (num & (1<<i)) { const char *q = sdb_fmt (0, "%s.0x%x", s, (1<<i)); const char *res = sdb_const_get (core->anal->sdb_types, q, 0); if (!empty) r_cons_printf (" | "); if (res) r_cons_printf ("%s", res); else r_cons_printf ("0x%x", (1<<i)); empty = 0; } } } else { eprintf ("This is not an enum\n"); } #endif } else { eprintf ("Missing value\n"); } free (s); } break; case 'e': { if (!input[1]) { eprintf ("Missing value\n"); break; } char *p, *s = strdup (input+2); const char *isenum; p = strchr (s, ' '); if (p) { *p++ = 0; isenum = sdb_const_get (core->anal->sdb_types, s, 0); if (isenum && !strcmp (isenum, "enum")) { const char *q = sdb_fmt (0, "%s.0x%x", s, (ut32)r_num_math (core->num, p)); const char *res = sdb_const_get (core->anal->sdb_types, q, 0); if (res) r_cons_printf ("%s\n", res); } else { eprintf ("This is not an enum\n"); } } else { eprintf ("Missing value\n"); } free (s); } break; case ' ': { const char *isenum = sdb_const_get (core->anal->sdb_types, input+2, 0); if (isenum && !strcmp (isenum, "enum")) { eprintf ("IS ENUM! \n"); } else { 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: 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, NULL, ""); 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[8192]; snprintf (tmp, sizeof (tmp)-1, "%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.%08"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"); } //else eprintf ("Cant find type at 0x%llx\n", addr); } break; case '?': show_help (core); break; } return true; }