Compute struct/union size in tsj/tuj ##format

This commit is contained in:
Gaurav Kumar Ghildiyal 2019-02-18 04:36:23 +05:30 committed by radare
parent f51e600340
commit 86e0862103
3 changed files with 96 additions and 7 deletions

View File

@ -334,6 +334,48 @@ static void cmd_type_noreturn(RCore *core, const char *input) {
}
}
/*!
* \brief Save the size of the given datatype in sdb
* \param sdb_types pointer to the sdb for types
* \param name the datatype whose size if to be stored
*/
static void save_type_size(Sdb *sdb_types, char *name) {
char *type = NULL;
r_return_if_fail (sdb_types && name);
if (!sdb_exists (sdb_types, name) || !(type = sdb_get (sdb_types, name, 0))) {
return;
}
char *type_name_size = r_str_newf ("%s.%s.%s", type, name, "size");
int size = r_type_get_bitsize (sdb_types, name);
sdb_set (sdb_types, type_name_size, sdb_fmt ("%d", size), 0);
free (type);
free (type_name_size);
}
/*!
* \brief Save the sizes of the datatypes which have been parsed
* \param core pointer to radare2 core
* \param parsed the parsed c string in sdb format
*/
R_API void save_parsed_type_size(RCore *core, const char *parsed) {
r_return_if_fail (core && core->anal && parsed);
char *str = strdup (parsed);
if (str) {
char *ptr = NULL;
int offset = 0;
while ((ptr = strstr (str + offset, "=struct\n")) || (ptr = strstr (str + offset, "=union\n"))) {
*ptr = 0;
char *name = ptr;
while (name - 1 >= str && *(name - 1) != '\n') {
name--;
}
save_type_size (core->anal->sdb_types, name);
offset = ptr + 1 - str;
}
free (str);
}
}
static void save_parsed_type(RCore *core, const char *parsed) {
if (!core || !core->anal || !parsed) {
return;
@ -353,6 +395,7 @@ static void save_parsed_type(RCore *core, const char *parsed) {
r_core_cmdf (core, "\"t- %s\"", name);
// Now add the type to sdb.
sdb_query_lines (core->anal->sdb_types, parsed);
save_parsed_type_size (core, parsed);
}
free (type);
}
@ -375,6 +418,46 @@ static int stdifstruct(void *user, const char *k, const char *v) {
return false;
}
/*!
* \brief print the data types details in JSON format
* \param TDB pointer to the sdb for types
* \param filter a callback function for the filtering
* \return 1 if success, 0 if failure
*/
static int print_struct_union_list_json(Sdb *TDB, SdbForeachCallback filter) {
PJ *pj = pj_new ();
if (!pj) {
return 0;
}
SdbList *l = sdb_foreach_list_filter (TDB, filter, true);
SdbListIter *it;
SdbKv *kv;
pj_a (pj); // [
ls_foreach (l, it, kv) {
const char *k = sdbkv_key (kv);
if (!k || !*k) {
continue;
}
pj_o (pj); // {
char *sizecmd = r_str_newf ("%s.%s.size", sdbkv_value (kv), k);
char *size_s = sdb_querys (TDB, NULL, -1, sizecmd);
pj_ks (pj, "type", k); // key value pair of string and string
pj_ki (pj, "size", size_s ? atoi (size_s) : 0); // key value pair of string and int
pj_end (pj); // }
free (sizecmd);
free (size_s);
}
pj_end (pj); // ]
r_cons_println (pj_string (pj));
pj_free (pj);
ls_free (l);
return 1;
}
static int printkey_cb(void *user, const char *k, const char *v) {
r_cons_println (k);
return 1;
@ -784,12 +867,12 @@ static int cmd_type(void *data, const char *input) {
ls_free (l);
}
break;
case 'j':
case 'j': // "tuj"
if (input[2]) {
showFormat (core, r_str_trim_ro (input + 2), 'j');
r_cons_newline ();
} else {
print_keys (TDB, core, stdifunion, printkey_json_cb, true);
print_struct_union_list_json (TDB, stdifunion);
}
break;
case 'c':{
@ -934,7 +1017,7 @@ static int cmd_type(void *data, const char *input) {
showFormat (core, r_str_trim_ro (input + 2), 'j');
r_cons_newline ();
} else {
print_keys (TDB, core, stdifstruct, printkey_json_cb, true);
print_struct_union_list_json (TDB, stdifstruct);
}
break;
}

View File

@ -498,6 +498,7 @@ R_API void r_core_print_func_args(RCore *core);
R_API char *resolve_fcn_name(RAnal *anal, const char * func_name);
R_API int r_core_get_stacksz (RCore *core, ut64 from, ut64 to);
R_API void save_parsed_type_size(RCore *core, const char *parsed);
/* anal.c */
R_API RAnalOp* r_core_anal_op(RCore *core, ut64 addr, int mask);

View File

@ -143,8 +143,8 @@ R_API int r_type_get_bitsize(Sdb *TDB, const char *type) {
query = sdb_fmt ("type.%s.size", tmptype);
return sdb_num_get (TDB, query, 0); // returns size in bits
}
if (!strcmp (t, "struct")) {
query = sdb_fmt ("struct.%s", tmptype);
if (!strcmp (t, "struct") || !strcmp (t, "union")) {
query = sdb_fmt ("%s.%s", t, tmptype);
char *members = sdb_get (TDB, query, 0);
char *next, *ptr = members;
int ret = 0;
@ -154,7 +154,7 @@ R_API int r_type_get_bitsize(Sdb *TDB, const char *type) {
if (!name) {
break;
}
query = sdb_fmt ("struct.%s.%s", tmptype, name);
query = sdb_fmt ("%s.%s.%s", t, tmptype, name);
char *subtype = sdb_get (TDB, query, 0);
if (!subtype) {
break;
@ -170,7 +170,12 @@ R_API int r_type_get_bitsize(Sdb *TDB, const char *type) {
if (elements == 0) {
elements = 1;
}
ret += r_type_get_bitsize (TDB, subtype) * elements;
if (!strcmp (t, "struct")) {
ret += r_type_get_bitsize (TDB, subtype) * elements;
} else {
int sz = r_type_get_bitsize (TDB, subtype) * elements;
ret = sz > ret ? sz : ret;
}
}
free (subtype);
ptr = next;