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); }
R_API RList* r_type_get_by_offset(Sdb *TDB, ut64 offset) { RList *offtypes = r_list_new (); SdbList *ls = sdb_foreach_list (TDB, true); SdbListIter *lsi; SdbKv *kv; ls_foreach (ls, lsi, kv) { // TODO: Add unions support if (!strncmp (kv->value, "struct", 6) && strncmp (kv->key, "struct.", 7)) { char *res = r_type_get_struct_memb (TDB, kv->key, offset); if (res) { r_list_append (offtypes, res); } } } ls_free (ls); return offtypes; }
R_API char *r_type_get_struct_memb(Sdb *TDB, const char *type, int offset) { int i, prev_typesize, 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; } prev_typesize = typesize; typesize += r_type_get_bitsize (TDB, subtype) * arrsz; // Handle nested structs if (offset < (typesize / 8)) { char *nested_type = (char *)r_str_word_get0 (subtype, 0); if (r_str_startswith (nested_type, "struct ") && !r_str_endswith (nested_type, " *")) { len = r_str_split (nested_type, ' '); if (len < 2) { free (subtype); break; } nested_type = (char *)r_str_word_get0 (nested_type, 1); char *nested_res = r_type_get_struct_memb (TDB, nested_type, offset - (prev_typesize / 8)); if (nested_res) { len = r_str_split(nested_res, '.'); res = r_str_newf ("%s.%s.%s", type, name, r_str_word_get0 (nested_res, len - 1)); free (nested_res); free (subtype); break; } } } free (subtype); } free (members); return res; }